Revert "Merge commit '8d14dbe041199d611839140f1c9285fd4174e9f4' ..."
Revert "Merging from ub-launcher3-master @ build 6877130" Revert "Merging from ub-launcher3-master @ build 6877130" Revert "Merging from ub-launcher3-master @ build 6877130" Revert submission 12738409-merge_ub-launcher3-master_6877130 Reason for revert: Introduced crashes to global presubmit Reverted Changes: I624658ce6:Merge commit '8d14dbe041199d611839140f1c9285fd4174... Iccd2f1e3a:Merging from ub-launcher3-master @ build 6877130 I791d64951:Merging from ub-launcher3-master @ build 6877130 Icdd32ab01:Merging from ub-launcher3-master @ build 6877130 Bug: 169963211 Change-Id: I77a4ae59e823147beae8dd7cb9b54ccdace2c7f4
This commit is contained in:
parent
49a94be109
commit
087a9e39b6
|
@ -36,12 +36,18 @@ LOCAL_STATIC_JAVA_LIBRARIES := \
|
|||
launcher_log_protos_lite
|
||||
|
||||
LOCAL_SRC_FILES := \
|
||||
$(call all-proto-files-under, protos) \
|
||||
$(call all-proto-files-under, proto_overrides) \
|
||||
$(call all-java-files-under, src_build_config) \
|
||||
|
||||
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
|
||||
|
||||
LOCAL_PROGUARD_ENABLED := disabled
|
||||
|
||||
LOCAL_PROTOC_OPTIMIZE_TYPE := nano
|
||||
LOCAL_PROTOC_FLAGS := --proto_path=$(LOCAL_PATH)/protos/ --proto_path=$(LOCAL_PATH)/proto_overrides/
|
||||
LOCAL_PROTO_JAVA_OUTPUT_PARAMS := enum_style=java
|
||||
|
||||
LOCAL_SDK_VERSION := current
|
||||
LOCAL_MIN_SDK_VERSION := 26
|
||||
LOCAL_MODULE := Launcher3CommonDepsLib
|
||||
|
@ -129,6 +135,7 @@ LOCAL_MODULE_TAGS := optional
|
|||
LOCAL_STATIC_JAVA_LIBRARIES := \
|
||||
SystemUI-statsd \
|
||||
SystemUISharedLib \
|
||||
launcherprotosnano \
|
||||
launcher_log_protos_lite
|
||||
ifneq (,$(wildcard frameworks/base))
|
||||
LOCAL_PRIVATE_PLATFORM_APIS := true
|
||||
|
@ -196,6 +203,7 @@ LOCAL_MODULE_TAGS := optional
|
|||
LOCAL_STATIC_JAVA_LIBRARIES := \
|
||||
SystemUI-statsd \
|
||||
SystemUISharedLib \
|
||||
launcherprotosnano \
|
||||
launcher_log_protos_lite
|
||||
ifneq (,$(wildcard frameworks/base))
|
||||
LOCAL_PRIVATE_PLATFORM_APIS := true
|
||||
|
|
24
build.gradle
24
build.gradle
|
@ -82,6 +82,7 @@ android {
|
|||
manifest.srcFile 'AndroidManifest-common.xml'
|
||||
proto {
|
||||
srcDir 'protos/'
|
||||
srcDir 'proto_overrides/'
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -149,6 +150,7 @@ dependencies {
|
|||
implementation "androidx.preference:preference:${ANDROID_X_VERSION}"
|
||||
implementation project(':IconLoader')
|
||||
withQuickstepImplementation project(':SharedLibWrapper')
|
||||
implementation fileTree(dir: "${FRAMEWORK_PREBUILTS_DIR}/libs", include: 'launcher_protos.jar')
|
||||
|
||||
// Recents lib dependency
|
||||
withQuickstepImplementation fileTree(dir: "${FRAMEWORK_PREBUILTS_DIR}/quickstep/libs", include: 'sysui_shared.jar')
|
||||
|
@ -169,16 +171,20 @@ dependencies {
|
|||
protobuf {
|
||||
// Configure the protoc executable
|
||||
protoc {
|
||||
artifact = "com.google.protobuf:protoc:${protocVersion}"
|
||||
}
|
||||
generateProtoTasks {
|
||||
all().each { task ->
|
||||
task.builtins {
|
||||
remove java
|
||||
java {
|
||||
option "lite"
|
||||
artifact = 'com.google.protobuf:protoc:3.0.0'
|
||||
|
||||
generateProtoTasks {
|
||||
all().each { task ->
|
||||
task.builtins {
|
||||
remove java
|
||||
javanano {
|
||||
option "java_package=launcher_log_extension.proto|com.android.launcher3.userevent.nano"
|
||||
option "java_package=launcher_log.proto|com.android.launcher3.userevent.nano"
|
||||
option "java_package=launcher_dump.proto|com.android.launcher3.model.nano"
|
||||
option "enum_style=java"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,245 @@
|
|||
/*
|
||||
* Copyright (C) 2016 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.
|
||||
*/
|
||||
syntax = "proto2";
|
||||
|
||||
import "launcher_log_extension.proto";
|
||||
|
||||
option java_package = "com.android.launcher3.userevent";
|
||||
option java_outer_classname = "LauncherLogProto";
|
||||
|
||||
package userevent;
|
||||
|
||||
message Target {
|
||||
enum Type {
|
||||
NONE = 0;
|
||||
ITEM = 1;
|
||||
CONTROL = 2;
|
||||
CONTAINER = 3;
|
||||
}
|
||||
|
||||
optional Type type = 1;
|
||||
|
||||
// For container type and item type
|
||||
// Used mainly for ContainerType.FOLDER, ItemType.*
|
||||
optional int32 page_index = 2;
|
||||
optional int32 rank = 3;
|
||||
optional int32 grid_x = 4;
|
||||
optional int32 grid_y = 5;
|
||||
|
||||
// For container types only
|
||||
optional ContainerType container_type = 6;
|
||||
optional int32 cardinality = 7;
|
||||
|
||||
// For control types only
|
||||
optional ControlType control_type = 8;
|
||||
|
||||
// For item types only
|
||||
optional ItemType item_type = 9;
|
||||
optional int32 package_name_hash = 10;
|
||||
optional int32 component_hash = 11; // Used for ItemType.WIDGET
|
||||
optional int32 intent_hash = 12; // Used for ItemType.SHORTCUT
|
||||
optional int32 span_x = 13 [default = 1];// Used for ItemType.WIDGET
|
||||
optional int32 span_y = 14 [default = 1];// Used for ItemType.WIDGET
|
||||
optional int32 predictedRank = 15;
|
||||
optional TargetExtension extension = 16;
|
||||
optional TipType tip_type = 17;
|
||||
optional int32 search_query_length = 18;
|
||||
optional bool is_work_app = 19;
|
||||
optional FromFolderLabelState from_folder_label_state = 20;
|
||||
optional ToFolderLabelState to_folder_label_state = 21;
|
||||
|
||||
// Note: proto does not support duplicate enum values, even if they belong to different enum type.
|
||||
// Hence "FROM" and "TO" prefix added.
|
||||
enum FromFolderLabelState {
|
||||
FROM_FOLDER_LABEL_STATE_UNSPECIFIED = 0;
|
||||
FROM_EMPTY = 1;
|
||||
FROM_CUSTOM = 2;
|
||||
FROM_SUGGESTED = 3;
|
||||
}
|
||||
|
||||
enum ToFolderLabelState {
|
||||
TO_FOLDER_LABEL_STATE_UNSPECIFIED = 0;
|
||||
TO_SUGGESTION0_WITH_VALID_PRIMARY = 1;
|
||||
TO_SUGGESTION1_WITH_VALID_PRIMARY = 2;
|
||||
TO_SUGGESTION1_WITH_EMPTY_PRIMARY = 3;
|
||||
TO_SUGGESTION2_WITH_VALID_PRIMARY = 4;
|
||||
TO_SUGGESTION2_WITH_EMPTY_PRIMARY = 5;
|
||||
TO_SUGGESTION3_WITH_VALID_PRIMARY = 6;
|
||||
TO_SUGGESTION3_WITH_EMPTY_PRIMARY = 7;
|
||||
TO_EMPTY_WITH_VALID_SUGGESTIONS = 8 [deprecated = true];
|
||||
TO_EMPTY_WITH_VALID_PRIMARY = 15;
|
||||
TO_EMPTY_WITH_VALID_SUGGESTIONS_AND_EMPTY_PRIMARY = 16;
|
||||
TO_EMPTY_WITH_EMPTY_SUGGESTIONS = 9;
|
||||
TO_EMPTY_WITH_SUGGESTIONS_DISABLED = 10;
|
||||
TO_CUSTOM_WITH_VALID_SUGGESTIONS = 11 [deprecated = true];
|
||||
TO_CUSTOM_WITH_VALID_PRIMARY = 17;
|
||||
TO_CUSTOM_WITH_VALID_SUGGESTIONS_AND_EMPTY_PRIMARY = 18;
|
||||
TO_CUSTOM_WITH_EMPTY_SUGGESTIONS = 12;
|
||||
TO_CUSTOM_WITH_SUGGESTIONS_DISABLED = 13;
|
||||
UNCHANGED = 14;
|
||||
}
|
||||
}
|
||||
|
||||
// Used to define what type of item a Target would represent.
|
||||
enum ItemType {
|
||||
DEFAULT_ITEMTYPE = 0;
|
||||
APP_ICON = 1;
|
||||
SHORTCUT = 2;
|
||||
WIDGET = 3;
|
||||
FOLDER_ICON = 4;
|
||||
DEEPSHORTCUT = 5;
|
||||
SEARCHBOX = 6;
|
||||
EDITTEXT = 7;
|
||||
NOTIFICATION = 8;
|
||||
TASK = 9; // Each page of Recents UI (QuickStep)
|
||||
WEB_APP = 10;
|
||||
TASK_ICON = 11;
|
||||
}
|
||||
|
||||
// Used to define what type of container a Target would represent.
|
||||
enum ContainerType {
|
||||
DEFAULT_CONTAINERTYPE = 0;
|
||||
WORKSPACE = 1;
|
||||
HOTSEAT = 2;
|
||||
FOLDER = 3;
|
||||
ALLAPPS = 4;
|
||||
WIDGETS = 5;
|
||||
OVERVIEW = 6; // Zoomed out workspace (without QuickStep)
|
||||
PREDICTION = 7;
|
||||
SEARCHRESULT = 8;
|
||||
DEEPSHORTCUTS = 9;
|
||||
PINITEM = 10; // confirmation screen
|
||||
NAVBAR = 11;
|
||||
TASKSWITCHER = 12; // Recents UI Container (QuickStep)
|
||||
APP = 13; // Foreground activity is another app (QuickStep)
|
||||
TIP = 14; // Onboarding texts (QuickStep)
|
||||
OTHER_LAUNCHER_APP = 15;
|
||||
}
|
||||
|
||||
// Used to define what type of control a Target would represent.
|
||||
enum ControlType {
|
||||
DEFAULT_CONTROLTYPE = 0;
|
||||
ALL_APPS_BUTTON = 1;
|
||||
WIDGETS_BUTTON = 2;
|
||||
WALLPAPER_BUTTON = 3;
|
||||
SETTINGS_BUTTON = 4;
|
||||
REMOVE_TARGET = 5;
|
||||
UNINSTALL_TARGET = 6;
|
||||
APPINFO_TARGET = 7;
|
||||
RESIZE_HANDLE = 8;
|
||||
VERTICAL_SCROLL = 9;
|
||||
HOME_INTENT = 10; // Deprecated, use enum Command instead
|
||||
BACK_BUTTON = 11;
|
||||
QUICK_SCRUB_BUTTON = 12;
|
||||
CLEAR_ALL_BUTTON = 13;
|
||||
CANCEL_TARGET = 14;
|
||||
TASK_PREVIEW = 15;
|
||||
SPLIT_SCREEN_TARGET = 16;
|
||||
REMOTE_ACTION_SHORTCUT = 17;
|
||||
APP_USAGE_SETTINGS = 18;
|
||||
BACK_GESTURE = 19;
|
||||
UNDO = 20;
|
||||
DISMISS_PREDICTION = 21;
|
||||
HYBRID_HOTSEAT_ACCEPTED = 22;
|
||||
HYBRID_HOTSEAT_CANCELED = 23;
|
||||
OVERVIEW_ACTIONS_SHARE_BUTTON = 24;
|
||||
OVERVIEW_ACTIONS_SCREENSHOT_BUTTON = 25;
|
||||
OVERVIEW_ACTIONS_SELECT_BUTTON = 26;
|
||||
SELECT_MODE_CLOSE_BUTTON = 27;
|
||||
SELECT_MODE_ITEM = 28;
|
||||
}
|
||||
|
||||
enum TipType {
|
||||
DEFAULT_NONE = 0;
|
||||
BOUNCE = 1;
|
||||
SWIPE_UP_TEXT = 2;
|
||||
QUICK_SCRUB_TEXT = 3;
|
||||
PREDICTION_TEXT = 4;
|
||||
DWB_TOAST = 5;
|
||||
HYBRID_HOTSEAT = 6;
|
||||
}
|
||||
|
||||
// Used to define the action component of the LauncherEvent.
|
||||
message Action {
|
||||
enum Type {
|
||||
TOUCH = 0;
|
||||
AUTOMATED = 1;
|
||||
COMMAND = 2;
|
||||
TIP = 3;
|
||||
SOFT_KEYBOARD = 4;
|
||||
// HARD_KEYBOARD, ASSIST
|
||||
}
|
||||
|
||||
enum Touch {
|
||||
TAP = 0;
|
||||
LONGPRESS = 1;
|
||||
DRAGDROP = 2;
|
||||
SWIPE = 3;
|
||||
FLING = 4;
|
||||
PINCH = 5;
|
||||
SWIPE_NOOP = 6;
|
||||
}
|
||||
|
||||
enum Direction {
|
||||
NONE = 0;
|
||||
UP = 1;
|
||||
DOWN = 2;
|
||||
LEFT = 3;
|
||||
RIGHT = 4;
|
||||
UPRIGHT = 5;
|
||||
UPLEFT = 6;
|
||||
}
|
||||
enum Command {
|
||||
HOME_INTENT = 0;
|
||||
BACK = 1;
|
||||
ENTRY = 2; // Indicates entry to one of Launcher container type target
|
||||
// not using the HOME_INTENT
|
||||
CANCEL = 3; // Indicates that a confirmation screen was cancelled
|
||||
CONFIRM = 4; // Indicates thata confirmation screen was accepted
|
||||
STOP = 5; // Indicates onStop() was called (screen time out, power off)
|
||||
RECENTS_BUTTON = 6; // Indicates that Recents button was pressed
|
||||
RESUME = 7; // Indicates onResume() was called
|
||||
}
|
||||
|
||||
optional Type type = 1;
|
||||
optional Touch touch = 2;
|
||||
optional Direction dir = 3;
|
||||
optional Command command = 4;
|
||||
// Log if the action was performed on outside of the container
|
||||
optional bool is_outside = 5;
|
||||
optional bool is_state_change = 6;
|
||||
}
|
||||
|
||||
//
|
||||
// Context free grammar of typical user interaction:
|
||||
// Action (Touch) + Target
|
||||
// Action (Touch) + Target + Target
|
||||
//
|
||||
message LauncherEvent {
|
||||
required Action action = 1;
|
||||
// List of targets that touch actions can be operated on.
|
||||
repeated Target src_target = 2;
|
||||
repeated Target dest_target = 3;
|
||||
|
||||
optional int64 action_duration_millis = 4;
|
||||
optional int64 elapsed_container_millis = 5;
|
||||
optional int64 elapsed_session_millis = 6;
|
||||
|
||||
optional bool is_in_multi_window_mode = 7 [deprecated = true];
|
||||
optional bool is_in_landscape_mode = 8 [deprecated = true];
|
||||
|
||||
optional LauncherEventExtension extension = 9;
|
||||
}
|
|
@ -13,8 +13,7 @@
|
|||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<com.android.quickstep.interaction.RootSandboxLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?android:attr/colorBackground">
|
||||
|
@ -94,11 +93,11 @@
|
|||
style="@style/TextAppearance.GestureTutorial.Feedback"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/gesture_tutorial_fragment_titles_container"
|
||||
android:layout_above="@id/gesture_tutorial_fragment_action_button"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginStart="@dimen/gesture_tutorial_feedback_margin_start_end"
|
||||
android:layout_marginEnd="@dimen/gesture_tutorial_feedback_margin_start_end"
|
||||
android:layout_marginTop="40dp"/>
|
||||
android:layout_marginBottom="10dp"/>
|
||||
|
||||
<!-- android:stateListAnimator="@null" removes shadow and normal on click behavior (increase
|
||||
of elevation and shadow) which is replaced by ripple effect in android:foreground -->
|
||||
|
@ -127,4 +126,4 @@
|
|||
android:background="@null"
|
||||
android:foreground="?android:attr/selectableItemBackgroundBorderless"
|
||||
android:stateListAnimator="@null"/>
|
||||
</com.android.quickstep.interaction.RootSandboxLayout>
|
||||
</RelativeLayout>
|
|
@ -149,21 +149,6 @@
|
|||
<!-- Feedback shown during interactive parts of Assistant gesture tutorial when the gesture doesn't go far enough. [CHAR LIMIT=100] -->
|
||||
<string name="assistant_gesture_feedback_swipe_not_long_enough" translatable="false">Try swiping further</string>
|
||||
|
||||
<!-- Title shown in sandbox mode part of gesture tutorial. [CHAR LIMIT=30] -->
|
||||
<string name="sandbox_mode_title" translatable="false">Sandbox Mode</string>
|
||||
<!-- Subtitle shown in sandbox mode part of gesture tutorial. [CHAR LIMIT=60] -->
|
||||
<string name="sandbox_mode_subtitle" translatable="false">Try any navigation gesture</string>
|
||||
<!-- Feedback shown in sandbox mode when the back gesture is successfully issued. [CHAR LIMIT=60] -->
|
||||
<string name="sandbox_mode_back_gesture_feedback_successful" translatable="false">Back gesture successful</string>
|
||||
<!-- Feedback shown in sandbox mode when the assistant gesture is a successfully issued. [CHAR LIMIT=60] -->
|
||||
<string name="sandbox_mode_assistant_gesture_feedback_successful" translatable="false">Assistant gesture successful</string>
|
||||
<!-- Feedback shown in sandbox mode when the home gesture is a successfully issued. [CHAR LIMIT=60] -->
|
||||
<string name="sandbox_mode_home_gesture_feedback_successful" translatable="false">Home gesture successful</string>
|
||||
<!-- Feedback shown in sandbox mode when the overview gesture is a successfully issued. [CHAR LIMIT=60] -->
|
||||
<string name="sandbox_mode_overview_gesture_feedback_successful" translatable="false">Overview gesture successful</string>
|
||||
<!-- Feedback shown in sandbox mode when the back gesture swipe is too far from the edge. [CHAR LIMIT=60] -->
|
||||
<string name="sandbox_mode_back_gesture_feedback_swipe_too_far_from_edge" translatable="false">Make sure you swipe from the left/right edge of the screen</string>
|
||||
|
||||
<!-- Title shown on the confirmation screen after successful gesture. [CHAR LIMIT=30] -->
|
||||
<string name="gesture_tutorial_confirm_title" translatable="false">All set</string>
|
||||
<!-- Button text shown on a button on the confirm screen to leave the tutorial. [CHAR LIMIT=14] -->
|
||||
|
|
|
@ -22,8 +22,6 @@ import static com.android.launcher3.LauncherState.NORMAL;
|
|||
import static com.android.quickstep.SysUINavigationMode.removeShelfFromOverview;
|
||||
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_HOME_KEY;
|
||||
|
||||
import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
|
||||
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.content.Intent;
|
||||
|
@ -309,10 +307,4 @@ public abstract class BaseQuickstepLauncher extends Launcher
|
|||
public void setHintUserWillBeActive() {
|
||||
addActivityFlags(ACTIVITY_STATE_USER_WILL_BE_ACTIVE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
InteractionJankMonitorWrapper.init(getWindow().getDecorView());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,7 +34,8 @@ import com.android.systemui.shared.system.RemoteAnimationRunnerCompat;
|
|||
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.P)
|
||||
public abstract class LauncherAnimationRunner implements RemoteAnimationRunnerCompat {
|
||||
public abstract class LauncherAnimationRunner implements RemoteAnimationRunnerCompat,
|
||||
WrappedAnimationRunnerImpl {
|
||||
|
||||
private static final String TAG = "LauncherAnimationRunner";
|
||||
|
||||
|
|
|
@ -66,7 +66,6 @@ import androidx.annotation.Nullable;
|
|||
|
||||
import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
|
||||
import com.android.launcher3.allapps.AllAppsTransitionController;
|
||||
import com.android.launcher3.anim.AnimationSuccessListener;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.dragndrop.DragLayer;
|
||||
import com.android.launcher3.shortcuts.DeepShortcutView;
|
||||
|
@ -82,7 +81,6 @@ import com.android.quickstep.util.StaggeredWorkspaceAnim;
|
|||
import com.android.quickstep.util.SurfaceTransactionApplier;
|
||||
import com.android.systemui.shared.system.ActivityCompat;
|
||||
import com.android.systemui.shared.system.ActivityOptionsCompat;
|
||||
import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
|
||||
import com.android.systemui.shared.system.QuickStepContract;
|
||||
import com.android.systemui.shared.system.RemoteAnimationAdapterCompat;
|
||||
import com.android.systemui.shared.system.RemoteAnimationDefinitionCompat;
|
||||
|
@ -797,36 +795,6 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans
|
|||
== PackageManager.PERMISSION_GRANTED;
|
||||
}
|
||||
|
||||
private void addCujInstrumentation(Animator anim, int cuj, String transition) {
|
||||
if (Trace.isEnabled()) {
|
||||
anim.addListener(new AnimationSuccessListener() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
Trace.beginAsyncSection(transition, 0);
|
||||
InteractionJankMonitorWrapper.begin(cuj);
|
||||
super.onAnimationStart(animation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationCancel(Animator animation) {
|
||||
super.onAnimationCancel(animation);
|
||||
InteractionJankMonitorWrapper.cancel(cuj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationSuccess(Animator animator) {
|
||||
InteractionJankMonitorWrapper.end(cuj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
super.onAnimationEnd(animation);
|
||||
Trace.endAsyncSection(TRANSITION_OPEN_LAUNCHER, 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remote animation runner for animation from the app to Launcher, including recents.
|
||||
*/
|
||||
|
@ -891,9 +859,21 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans
|
|||
// is initialized.
|
||||
if (launcherIsATargetWithMode(appTargets, MODE_OPENING)
|
||||
|| mLauncher.isForceInvisible()) {
|
||||
addCujInstrumentation(
|
||||
anim, InteractionJankMonitorWrapper.CUJ_APP_CLOSE_TO_HOME,
|
||||
TRANSITION_OPEN_LAUNCHER);
|
||||
if (Trace.isEnabled()) {
|
||||
anim.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
Trace.beginAsyncSection(TRANSITION_OPEN_LAUNCHER, 0);
|
||||
super.onAnimationStart(animation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
super.onAnimationEnd(animation);
|
||||
Trace.endAsyncSection(TRANSITION_OPEN_LAUNCHER, 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
// Only register the content animation for cancellation when state changes
|
||||
mLauncher.getStateManager().setCurrentAnimation(anim);
|
||||
|
||||
|
@ -962,12 +942,25 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans
|
|||
launcherClosing);
|
||||
}
|
||||
|
||||
addCujInstrumentation(anim,
|
||||
launchingFromRecents
|
||||
? InteractionJankMonitorWrapper.CUJ_APP_LAUNCH_FROM_RECENTS
|
||||
: InteractionJankMonitorWrapper.CUJ_APP_LAUNCH_FROM_ICON,
|
||||
launchingFromRecents
|
||||
? TRANSITION_LAUNCH_FROM_RECENTS : TRANSITION_LAUNCH_FROM_ICON);
|
||||
if (Trace.isEnabled()) {
|
||||
final String section =
|
||||
launchingFromRecents
|
||||
? TRANSITION_LAUNCH_FROM_RECENTS : TRANSITION_LAUNCH_FROM_ICON;
|
||||
|
||||
anim.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
Trace.beginAsyncSection(section, 0);
|
||||
super.onAnimationStart(animation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
super.onAnimationEnd(animation);
|
||||
Trace.endAsyncSection(section, 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (launcherClosing) {
|
||||
anim.addListener(mForceInvisibleListener);
|
||||
|
|
|
@ -16,8 +16,11 @@
|
|||
|
||||
package com.android.launcher3.appprediction;
|
||||
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound;
|
||||
import static com.android.launcher3.logging.LoggerUtils.newContainerTarget;
|
||||
import static com.android.launcher3.logging.LoggerUtils.newTarget;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
|
@ -40,6 +43,7 @@ import com.android.launcher3.DeviceProfile;
|
|||
import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.allapps.AllAppsSectionDecorator;
|
||||
import com.android.launcher3.allapps.FloatingHeaderRow;
|
||||
|
@ -49,11 +53,13 @@ import com.android.launcher3.anim.PropertySetter;
|
|||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.keyboard.FocusIndicatorHelper;
|
||||
import com.android.launcher3.keyboard.FocusIndicatorHelper.SimpleFocusIndicatorHelper;
|
||||
import com.android.launcher3.logging.StatsLogUtils.LogContainerProvider;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.ItemInfoWithIcon;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.touch.ItemClickHandler;
|
||||
import com.android.launcher3.touch.ItemLongClickListener;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||
import com.android.launcher3.util.Themes;
|
||||
import com.android.quickstep.AnimatedFloat;
|
||||
|
||||
|
@ -62,7 +68,7 @@ import java.util.List;
|
|||
|
||||
@TargetApi(Build.VERSION_CODES.P)
|
||||
public class PredictionRowView extends LinearLayout implements
|
||||
OnDeviceProfileChangeListener, FloatingHeaderRow {
|
||||
LogContainerProvider, OnDeviceProfileChangeListener, FloatingHeaderRow {
|
||||
|
||||
private static final IntProperty<PredictionRowView> TEXT_ALPHA =
|
||||
new IntProperty<PredictionRowView>("textAlpha") {
|
||||
|
@ -265,6 +271,29 @@ public class PredictionRowView extends LinearLayout implements
|
|||
mParent.onHeightUpdated();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillInLogContainerData(ItemInfo childInfo, LauncherLogProto.Target child,
|
||||
ArrayList<LauncherLogProto.Target> parents) {
|
||||
for (int i = 0; i < mPredictedApps.size(); i++) {
|
||||
ItemInfoWithIcon appInfo = mPredictedApps.get(i);
|
||||
if (appInfo == childInfo) {
|
||||
child.predictedRank = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
parents.add(newContainerTarget(LauncherLogProto.ContainerType.PREDICTION));
|
||||
|
||||
// include where the prediction is coming this used to be Launcher#modifyUserEvent
|
||||
LauncherLogProto.Target parent = newTarget(LauncherLogProto.Target.Type.CONTAINER);
|
||||
LauncherState state = mLauncher.getStateManager().getState();
|
||||
if (state == LauncherState.ALL_APPS) {
|
||||
parent.containerType = LauncherLogProto.ContainerType.ALLAPPS;
|
||||
} else if (state == OVERVIEW) {
|
||||
parent.containerType = LauncherLogProto.ContainerType.TASKSWITCHER;
|
||||
}
|
||||
parents.add(parent);
|
||||
}
|
||||
|
||||
public void setTextAlpha(int textAlpha) {
|
||||
mIconLastSetTextAlpha = textAlpha;
|
||||
if (getAlpha() < 1 && textAlpha > 0) {
|
||||
|
|
|
@ -55,6 +55,7 @@ import com.android.launcher3.popup.SystemShortcut;
|
|||
import com.android.launcher3.touch.ItemLongClickListener;
|
||||
import com.android.launcher3.uioverrides.PredictedAppIcon;
|
||||
import com.android.launcher3.uioverrides.QuickstepLauncher;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||
import com.android.launcher3.util.OnboardingPrefs;
|
||||
import com.android.launcher3.views.ArrowTipView;
|
||||
import com.android.launcher3.views.Snackbar;
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
package com.android.launcher3.uioverrides.states;
|
||||
|
||||
import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_ALLAPPS;
|
||||
import static com.android.quickstep.SysUINavigationMode.removeShelfFromOverview;
|
||||
|
||||
import android.content.Context;
|
||||
|
@ -24,6 +23,7 @@ import android.content.Context;
|
|||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.allapps.AllAppsContainerView;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
||||
|
||||
/**
|
||||
* Definition for AllApps state
|
||||
|
@ -40,7 +40,7 @@ public class AllAppsState extends LauncherState {
|
|||
};
|
||||
|
||||
public AllAppsState(int id) {
|
||||
super(id, LAUNCHER_STATE_ALLAPPS, STATE_FLAGS);
|
||||
super(id, ContainerType.ALLAPPS, STATE_FLAGS);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -15,13 +15,12 @@
|
|||
*/
|
||||
package com.android.launcher3.uioverrides.states;
|
||||
|
||||
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_BACKGROUND;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.android.launcher3.BaseDraggingActivity;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.allapps.AllAppsTransitionController;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||
import com.android.quickstep.util.LayoutUtils;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
|
||||
|
@ -34,7 +33,7 @@ public class BackgroundAppState extends OverviewState {
|
|||
| FLAG_WORKSPACE_INACCESSIBLE | FLAG_NON_INTERACTIVE | FLAG_CLOSE_POPUPS;
|
||||
|
||||
public BackgroundAppState(int id) {
|
||||
this(id, LAUNCHER_STATE_BACKGROUND);
|
||||
this(id, LauncherLogProto.ContainerType.TASKSWITCHER);
|
||||
}
|
||||
|
||||
protected BackgroundAppState(int id, int logContainer) {
|
||||
|
|
|
@ -15,14 +15,13 @@
|
|||
*/
|
||||
package com.android.launcher3.uioverrides.states;
|
||||
|
||||
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_OVERVIEW;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
|
||||
import com.android.launcher3.BaseDraggingActivity;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
|
||||
/**
|
||||
|
@ -35,7 +34,7 @@ public class OverviewModalTaskState extends OverviewState {
|
|||
FLAG_DISABLE_RESTORE | FLAG_OVERVIEW_UI | FLAG_WORKSPACE_INACCESSIBLE;
|
||||
|
||||
public OverviewModalTaskState(int id) {
|
||||
super(id, LAUNCHER_STATE_OVERVIEW, STATE_FLAGS);
|
||||
super(id, ContainerType.OVERVIEW, STATE_FLAGS);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
package com.android.launcher3.uioverrides.states;
|
||||
|
||||
import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_OVERVIEW;
|
||||
import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
|
||||
import static com.android.quickstep.SysUINavigationMode.hideShelfInTwoButtonLandscape;
|
||||
import static com.android.quickstep.SysUINavigationMode.removeShelfFromOverview;
|
||||
|
@ -30,6 +29,7 @@ import com.android.launcher3.Launcher;
|
|||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Workspace;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
||||
import com.android.quickstep.SysUINavigationMode;
|
||||
import com.android.quickstep.util.LayoutUtils;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
|
@ -51,7 +51,7 @@ public class OverviewState extends LauncherState {
|
|||
}
|
||||
|
||||
protected OverviewState(int id, int stateFlags) {
|
||||
this(id, LAUNCHER_STATE_OVERVIEW, stateFlags);
|
||||
this(id, ContainerType.TASKSWITCHER, stateFlags);
|
||||
}
|
||||
|
||||
protected OverviewState(int id, int logContainer, int stateFlags) {
|
||||
|
|
|
@ -15,9 +15,8 @@
|
|||
*/
|
||||
package com.android.launcher3.uioverrides.states;
|
||||
|
||||
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_BACKGROUND;
|
||||
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||
|
||||
/**
|
||||
* State to indicate we are about to launch a recent task. Note that this state is only used when
|
||||
|
@ -27,7 +26,7 @@ import com.android.launcher3.Launcher;
|
|||
public class QuickSwitchState extends BackgroundAppState {
|
||||
|
||||
public QuickSwitchState(int id) {
|
||||
super(id, LAUNCHER_STATE_BACKGROUND);
|
||||
super(id, LauncherLogProto.ContainerType.APP);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -12,6 +12,8 @@ import com.android.launcher3.LauncherState;
|
|||
import com.android.launcher3.states.StateAnimationConfig.AnimationFlags;
|
||||
import com.android.launcher3.touch.AbstractStateChangeTouchController;
|
||||
import com.android.launcher3.touch.SingleAxisSwipeDetector;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
|
||||
import com.android.quickstep.SystemUiProxy;
|
||||
|
||||
/**
|
||||
|
@ -43,6 +45,11 @@ public class LandscapeEdgeSwipeController extends AbstractStateChangeTouchContro
|
|||
return draggingFromNav ? OVERVIEW : NORMAL;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getLogContainerTypeForNormalState(MotionEvent ev) {
|
||||
return LauncherLogProto.ContainerType.NAVBAR;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getShiftRange() {
|
||||
return mLauncher.getDragLayer().getWidth();
|
||||
|
@ -58,8 +65,13 @@ public class LandscapeEdgeSwipeController extends AbstractStateChangeTouchContro
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void onSwipeInteractionCompleted(LauncherState targetState) {
|
||||
super.onSwipeInteractionCompleted(targetState);
|
||||
protected int getDirectionForLog() {
|
||||
return mLauncher.getDeviceProfile().isSeascape() ? Direction.RIGHT : Direction.LEFT;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSwipeInteractionCompleted(LauncherState targetState, int logAction) {
|
||||
super.onSwipeInteractionCompleted(targetState, logAction);
|
||||
if (mStartState == NORMAL && targetState == OVERVIEW) {
|
||||
SystemUiProxy.INSTANCE.get(mLauncher).onOverviewShown(true, TAG);
|
||||
}
|
||||
|
|
|
@ -45,9 +45,12 @@ import com.android.launcher3.anim.PendingAnimation;
|
|||
import com.android.launcher3.compat.AccessibilityManagerCompat;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.graphics.OverviewScrim;
|
||||
import com.android.launcher3.logging.StatsLogManager;
|
||||
import com.android.launcher3.states.StateAnimationConfig;
|
||||
import com.android.launcher3.testing.TestProtocol;
|
||||
import com.android.launcher3.touch.SingleAxisSwipeDetector;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
|
||||
import com.android.launcher3.util.TouchController;
|
||||
import com.android.quickstep.util.AnimatorControllerWithResistance;
|
||||
import com.android.quickstep.util.AssistantUtilities;
|
||||
|
@ -208,6 +211,7 @@ public class NavBarToHomeTouchController implements TouchController,
|
|||
@Override
|
||||
public void onDragEnd(float velocity) {
|
||||
boolean fling = mSwipeDetector.isFling(velocity);
|
||||
final int logAction = fling ? Touch.FLING : Touch.SWIPE;
|
||||
float progress = mCurrentAnimation.getProgressFraction();
|
||||
float interpolatedProgress = PULLBACK_INTERPOLATOR.getInterpolation(progress);
|
||||
boolean success = interpolatedProgress >= SUCCESS_TRANSITION_PROGRESS
|
||||
|
@ -226,7 +230,7 @@ public class NavBarToHomeTouchController implements TouchController,
|
|||
() -> onSwipeInteractionCompleted(mEndState));
|
||||
}
|
||||
if (mStartState != mEndState) {
|
||||
logHomeGesture();
|
||||
// TODO: add to WW log
|
||||
}
|
||||
AbstractFloatingView topOpenView = AbstractFloatingView.getTopOpenView(mLauncher);
|
||||
if (topOpenView != null) {
|
||||
|
@ -251,10 +255,17 @@ public class NavBarToHomeTouchController implements TouchController,
|
|||
AccessibilityManagerCompat.sendStateEventToTest(mLauncher, targetState.ordinal);
|
||||
}
|
||||
|
||||
private void logHomeGesture() {
|
||||
private void logStateChange(int startContainerType, int logAction) {
|
||||
mLauncher.getUserEventDispatcher().logStateChangeAction(logAction,
|
||||
LauncherLogProto.Action.Direction.UP,
|
||||
mSwipeDetector.getDownX(), mSwipeDetector.getDownY(),
|
||||
LauncherLogProto.ContainerType.NAVBAR,
|
||||
startContainerType,
|
||||
mEndState.containerType,
|
||||
mLauncher.getWorkspace().getCurrentPage());
|
||||
mLauncher.getStatsLogManager().logger()
|
||||
.withSrcState(mStartState.statsLogOrdinal)
|
||||
.withDstState(mEndState.statsLogOrdinal)
|
||||
.withSrcState(StatsLogManager.containerTypeToAtomState(mStartState.containerType))
|
||||
.withDstState(StatsLogManager.containerTypeToAtomState(mEndState.containerType))
|
||||
.log(LAUNCHER_HOME_GESTURE);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,6 +49,7 @@ import com.android.launcher3.anim.Interpolators;
|
|||
import com.android.launcher3.graphics.OverviewScrim;
|
||||
import com.android.launcher3.states.StateAnimationConfig;
|
||||
import com.android.launcher3.testing.TestProtocol;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
|
||||
import com.android.launcher3.util.VibratorWrapper;
|
||||
import com.android.quickstep.SystemUiProxy;
|
||||
import com.android.quickstep.util.AnimatorControllerWithResistance;
|
||||
|
@ -206,7 +207,7 @@ public class NoButtonNavbarToOverviewTouchController extends PortraitStatesTouch
|
|||
|
||||
private void maybeSwipeInteractionToOverviewComplete() {
|
||||
if (mReachedOverview && mDetector.isSettlingState()) {
|
||||
onSwipeInteractionCompleted(OVERVIEW);
|
||||
onSwipeInteractionCompleted(OVERVIEW, Touch.SWIPE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -250,7 +251,7 @@ public class NoButtonNavbarToOverviewTouchController extends PortraitStatesTouch
|
|||
private void goToOverviewOrHomeOnDragEnd(float velocity) {
|
||||
boolean goToHomeInsteadOfOverview = !mMotionPauseDetector.isPaused();
|
||||
if (goToHomeInsteadOfOverview) {
|
||||
new OverviewToHomeAnim(mLauncher, ()-> onSwipeInteractionCompleted(NORMAL))
|
||||
new OverviewToHomeAnim(mLauncher, ()-> onSwipeInteractionCompleted(NORMAL, Touch.FLING))
|
||||
.animateWithVelocity(velocity);
|
||||
}
|
||||
if (mReachedOverview) {
|
||||
|
|
|
@ -57,9 +57,13 @@ import com.android.launcher3.Utilities;
|
|||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||
import com.android.launcher3.anim.PendingAnimation;
|
||||
import com.android.launcher3.graphics.OverviewScrim;
|
||||
import com.android.launcher3.logging.StatsLogManager;
|
||||
import com.android.launcher3.states.StateAnimationConfig;
|
||||
import com.android.launcher3.touch.BaseSwipeDetector;
|
||||
import com.android.launcher3.touch.BothAxesSwipeDetector;
|
||||
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.launcher3.util.TouchController;
|
||||
import com.android.launcher3.util.VibratorWrapper;
|
||||
import com.android.quickstep.AnimatedFloat;
|
||||
|
@ -283,6 +287,7 @@ public class NoButtonQuickSwitchTouchController implements TouchController,
|
|||
boolean horizontalFling = mSwipeDetector.isFling(velocity.x);
|
||||
boolean verticalFling = mSwipeDetector.isFling(velocity.y);
|
||||
boolean noFling = !horizontalFling && !verticalFling;
|
||||
int logAction = noFling ? Touch.SWIPE : Touch.FLING;
|
||||
if (mMotionPauseDetector.isPaused() && noFling) {
|
||||
cancelAnimations();
|
||||
|
||||
|
@ -293,7 +298,7 @@ public class NoButtonQuickSwitchTouchController implements TouchController,
|
|||
overviewAnim.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
onAnimationToStateCompleted(OVERVIEW);
|
||||
onAnimationToStateCompleted(OVERVIEW, logAction);
|
||||
}
|
||||
});
|
||||
overviewAnim.start();
|
||||
|
@ -388,7 +393,7 @@ public class NoButtonQuickSwitchTouchController implements TouchController,
|
|||
}
|
||||
|
||||
nonOverviewAnim.setDuration(Math.max(xDuration, yDuration));
|
||||
mNonOverviewAnim.setEndAction(() -> onAnimationToStateCompleted(targetState));
|
||||
mNonOverviewAnim.setEndAction(() -> onAnimationToStateCompleted(targetState, logAction));
|
||||
|
||||
cancelAnimations();
|
||||
xOverviewAnim.start();
|
||||
|
@ -396,17 +401,27 @@ public class NoButtonQuickSwitchTouchController implements TouchController,
|
|||
nonOverviewAnim.start();
|
||||
}
|
||||
|
||||
private void onAnimationToStateCompleted(LauncherState targetState) {
|
||||
private void onAnimationToStateCompleted(LauncherState targetState, int logAction) {
|
||||
mLauncher.getUserEventDispatcher().logStateChangeAction(logAction,
|
||||
getDirectionForLog(), mSwipeDetector.getDownX(), mSwipeDetector.getDownY(),
|
||||
LauncherLogProto.ContainerType.NAVBAR,
|
||||
mStartState.containerType,
|
||||
targetState.containerType,
|
||||
mLauncher.getWorkspace().getCurrentPage());
|
||||
mLauncher.getStatsLogManager().logger()
|
||||
.withSrcState(LAUNCHER_STATE_HOME)
|
||||
.withDstState(targetState.statsLogOrdinal)
|
||||
.log(getLauncherAtomEvent(mStartState.statsLogOrdinal, targetState.statsLogOrdinal,
|
||||
.withDstState(StatsLogManager.containerTypeToAtomState(targetState.containerType))
|
||||
.log(getLauncherAtomEvent(mStartState.containerType, targetState.containerType,
|
||||
targetState.ordinal > mStartState.ordinal
|
||||
? LAUNCHER_UNKNOWN_SWIPEUP
|
||||
: LAUNCHER_UNKNOWN_SWIPEDOWN));
|
||||
mLauncher.getStateManager().goToState(targetState, false, this::clearState);
|
||||
}
|
||||
|
||||
private int getDirectionForLog() {
|
||||
return Utilities.isRtl(mLauncher.getResources()) ? Direction.LEFT : Direction.RIGHT;
|
||||
}
|
||||
|
||||
private void cancelAnimations() {
|
||||
if (mNonOverviewAnim != null) {
|
||||
mNonOverviewAnim.getAnimationPlayer().cancel();
|
||||
|
|
|
@ -25,6 +25,7 @@ import com.android.launcher3.AbstractFloatingView;
|
|||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||
import com.android.quickstep.TouchInteractionService;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
|
||||
|
@ -72,4 +73,9 @@ public class OverviewToAllAppsTouchController extends PortraitStatesTouchControl
|
|||
}
|
||||
return fromState;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getLogContainerTypeForNormalState(MotionEvent ev) {
|
||||
return LauncherLogProto.ContainerType.WORKSPACE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,6 +48,8 @@ import com.android.launcher3.testing.TestProtocol;
|
|||
import com.android.launcher3.touch.AbstractStateChangeTouchController;
|
||||
import com.android.launcher3.touch.SingleAxisSwipeDetector;
|
||||
import com.android.launcher3.uioverrides.states.OverviewState;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
||||
import com.android.quickstep.SystemUiProxy;
|
||||
import com.android.quickstep.TouchInteractionService;
|
||||
import com.android.quickstep.util.LayoutUtils;
|
||||
|
@ -170,6 +172,11 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr
|
|||
return fromState;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getLogContainerTypeForNormalState(MotionEvent ev) {
|
||||
return isTouchOverHotseat(mLauncher, ev) ? ContainerType.HOTSEAT : ContainerType.WORKSPACE;
|
||||
}
|
||||
|
||||
private StateAnimationConfig getNormalToOverviewAnimation() {
|
||||
mAllAppsInterpolatorWrapper.baseInterpolator = LINEAR;
|
||||
|
||||
|
@ -278,7 +285,7 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr
|
|||
|
||||
private void cancelPendingAnim() {
|
||||
if (mPendingAnimation != null) {
|
||||
mPendingAnimation.finish(false);
|
||||
mPendingAnimation.finish(false, Touch.SWIPE);
|
||||
mPendingAnimation = null;
|
||||
}
|
||||
}
|
||||
|
@ -313,8 +320,8 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void onSwipeInteractionCompleted(LauncherState targetState) {
|
||||
super.onSwipeInteractionCompleted(targetState);
|
||||
protected void onSwipeInteractionCompleted(LauncherState targetState, int logAction) {
|
||||
super.onSwipeInteractionCompleted(targetState, logAction);
|
||||
if (mStartState == NORMAL && targetState == OVERVIEW) {
|
||||
SystemUiProxy.INSTANCE.get(mLauncher).onOverviewShown(true, TAG);
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@ import static com.android.launcher3.anim.Interpolators.ACCEL_2;
|
|||
import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
|
||||
import static com.android.launcher3.anim.Interpolators.INSTANT;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_BACKGROUND;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE;
|
||||
|
@ -42,6 +41,8 @@ import com.android.launcher3.Utilities;
|
|||
import com.android.launcher3.states.StateAnimationConfig;
|
||||
import com.android.launcher3.touch.AbstractStateChangeTouchController;
|
||||
import com.android.launcher3.touch.SingleAxisSwipeDetector;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
|
||||
import com.android.quickstep.SysUINavigationMode;
|
||||
import com.android.quickstep.SysUINavigationMode.Mode;
|
||||
import com.android.quickstep.SystemUiProxy;
|
||||
|
@ -91,14 +92,14 @@ public class QuickSwitchTouchController extends AbstractStateChangeTouchControll
|
|||
@Override
|
||||
public void onDragStart(boolean start, float startDisplacement) {
|
||||
super.onDragStart(start, startDisplacement);
|
||||
mStartContainerType = LAUNCHER_STATE_BACKGROUND;
|
||||
mStartContainerType = LauncherLogProto.ContainerType.NAVBAR;
|
||||
ActivityManagerWrapper.getInstance()
|
||||
.closeSystemWindows(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSwipeInteractionCompleted(LauncherState targetState) {
|
||||
super.onSwipeInteractionCompleted(targetState);
|
||||
protected void onSwipeInteractionCompleted(LauncherState targetState, int logAction) {
|
||||
super.onSwipeInteractionCompleted(targetState, logAction);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -152,4 +153,14 @@ public class QuickSwitchTouchController extends AbstractStateChangeTouchControll
|
|||
protected float getShiftRange() {
|
||||
return mLauncher.getDeviceProfile().widthPx / 2f;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getLogContainerTypeForNormalState(MotionEvent ev) {
|
||||
return LauncherLogProto.ContainerType.NAVBAR;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getDirectionForLog() {
|
||||
return Utilities.isRtl(mLauncher.getResources()) ? Direction.LEFT : Direction.RIGHT;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,12 +15,10 @@
|
|||
*/
|
||||
package com.android.launcher3.uioverrides.touchcontrollers;
|
||||
|
||||
import static android.view.MotionEvent.ACTION_CANCEL;
|
||||
import static android.view.MotionEvent.ACTION_DOWN;
|
||||
import static android.view.MotionEvent.ACTION_MOVE;
|
||||
import static android.view.MotionEvent.ACTION_UP;
|
||||
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SWIPE_DOWN_WORKSPACE_NOTISHADE_OPEN;
|
||||
import static android.view.MotionEvent.ACTION_CANCEL;
|
||||
|
||||
import android.graphics.PointF;
|
||||
import android.util.SparseArray;
|
||||
|
@ -33,9 +31,12 @@ import com.android.launcher3.AbstractFloatingView;
|
|||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
||||
import com.android.launcher3.util.TouchController;
|
||||
import com.android.quickstep.SystemUiProxy;
|
||||
|
||||
import com.android.quickstep.SystemUiProxy;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
/**
|
||||
|
@ -132,8 +133,9 @@ public class StatusBarTouchController implements TouchController {
|
|||
int action = ev.getAction();
|
||||
if (action == ACTION_UP || action == ACTION_CANCEL) {
|
||||
dispatchTouchEvent(ev);
|
||||
mLauncher.getStatsLogManager().logger()
|
||||
.log(LAUNCHER_SWIPE_DOWN_WORKSPACE_NOTISHADE_OPEN);
|
||||
mLauncher.getUserEventDispatcher().logActionOnContainer(action == ACTION_UP ?
|
||||
Touch.FLING : Touch.SWIPE, Direction.DOWN, ContainerType.WORKSPACE,
|
||||
mLauncher.getWorkspace().getCurrentPage());
|
||||
setWindowSlippery(false);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ import com.android.launcher3.anim.PendingAnimation;
|
|||
import com.android.launcher3.touch.BaseSwipeDetector;
|
||||
import com.android.launcher3.touch.PagedOrientationHandler;
|
||||
import com.android.launcher3.touch.SingleAxisSwipeDetector;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
|
||||
import com.android.launcher3.util.FlingBlockCheck;
|
||||
import com.android.launcher3.util.TouchController;
|
||||
import com.android.launcher3.views.BaseDragLayer;
|
||||
|
@ -202,7 +203,7 @@ public abstract class TaskViewTouchController<T extends BaseDraggingActivity>
|
|||
mCurrentAnimation.setPlayFraction(0);
|
||||
}
|
||||
if (mPendingAnimation != null) {
|
||||
mPendingAnimation.finish(false);
|
||||
mPendingAnimation.finish(false, Touch.SWIPE);
|
||||
mPendingAnimation = null;
|
||||
}
|
||||
|
||||
|
@ -284,6 +285,7 @@ public abstract class TaskViewTouchController<T extends BaseDraggingActivity>
|
|||
public void onDragEnd(float velocity) {
|
||||
boolean fling = mDetector.isFling(velocity);
|
||||
final boolean goingToEnd;
|
||||
final int logAction;
|
||||
boolean blockedFling = fling && mFlingBlockCheck.isBlocked();
|
||||
if (blockedFling) {
|
||||
fling = false;
|
||||
|
@ -292,9 +294,11 @@ public abstract class TaskViewTouchController<T extends BaseDraggingActivity>
|
|||
float progress = mCurrentAnimation.getProgressFraction();
|
||||
float interpolatedProgress = mCurrentAnimation.getInterpolatedProgress();
|
||||
if (fling) {
|
||||
logAction = Touch.FLING;
|
||||
boolean goingUp = orientationHandler.isGoingUp(velocity, mIsRtl);
|
||||
goingToEnd = goingUp == mCurrentAnimationIsGoingUp;
|
||||
} else {
|
||||
logAction = Touch.SWIPE;
|
||||
goingToEnd = interpolatedProgress > SUCCESS_TRANSITION_PROGRESS;
|
||||
}
|
||||
long animationDuration = BaseSwipeDetector.calculateDuration(
|
||||
|
@ -303,14 +307,14 @@ public abstract class TaskViewTouchController<T extends BaseDraggingActivity>
|
|||
animationDuration *= LauncherAnimUtils.blockedFlingDurationFactor(velocity);
|
||||
}
|
||||
|
||||
mCurrentAnimation.setEndAction(() -> onCurrentAnimationEnd(goingToEnd));
|
||||
mCurrentAnimation.setEndAction(() -> onCurrentAnimationEnd(goingToEnd, logAction));
|
||||
mCurrentAnimation.startWithVelocity(mActivity, goingToEnd,
|
||||
velocity, mEndDisplacement, animationDuration);
|
||||
}
|
||||
|
||||
private void onCurrentAnimationEnd(boolean wasSuccess) {
|
||||
private void onCurrentAnimationEnd(boolean wasSuccess, int logAction) {
|
||||
if (mPendingAnimation != null) {
|
||||
mPendingAnimation.finish(wasSuccess);
|
||||
mPendingAnimation.finish(wasSuccess, logAction);
|
||||
mPendingAnimation = null;
|
||||
}
|
||||
clearState();
|
||||
|
@ -322,7 +326,7 @@ public abstract class TaskViewTouchController<T extends BaseDraggingActivity>
|
|||
mTaskBeingDragged = null;
|
||||
mCurrentAnimation = null;
|
||||
if (mPendingAnimation != null) {
|
||||
mPendingAnimation.finish(false);
|
||||
mPendingAnimation.finish(false, Touch.SWIPE);
|
||||
mPendingAnimation = null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -75,8 +75,12 @@ import com.android.launcher3.anim.AnimationSuccessListener;
|
|||
import com.android.launcher3.anim.Interpolators;
|
||||
import com.android.launcher3.logging.StatsLogManager;
|
||||
import com.android.launcher3.logging.StatsLogManager.StatsLogger;
|
||||
import com.android.launcher3.logging.UserEventDispatcher;
|
||||
import com.android.launcher3.statemanager.StatefulActivity;
|
||||
import com.android.launcher3.testing.TestProtocol;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
||||
import com.android.launcher3.util.TraceHelper;
|
||||
import com.android.launcher3.util.VibratorWrapper;
|
||||
import com.android.launcher3.util.WindowBounds;
|
||||
|
@ -97,7 +101,6 @@ import com.android.quickstep.views.TaskView;
|
|||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
import com.android.systemui.shared.system.ActivityManagerWrapper;
|
||||
import com.android.systemui.shared.system.InputConsumerController;
|
||||
import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
|
||||
import com.android.systemui.shared.system.LatencyTrackerCompat;
|
||||
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
|
||||
import com.android.systemui.shared.system.TaskInfoCompat;
|
||||
|
@ -216,7 +219,8 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<?>, Q extends
|
|||
|
||||
private boolean mPassedOverviewThreshold;
|
||||
private boolean mGestureStarted;
|
||||
private boolean mLogDirectionUpOrLeft = true;
|
||||
private int mLogAction = Touch.SWIPE;
|
||||
private int mLogDirection = Direction.UP;
|
||||
private PointF mDownPos;
|
||||
private boolean mIsLikelyToStartNewTask;
|
||||
|
||||
|
@ -430,13 +434,9 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<?>, Q extends
|
|||
mOnDeferredActivityLaunch);
|
||||
|
||||
mGestureState.runOnceAtState(STATE_END_TARGET_SET,
|
||||
() -> {
|
||||
mDeviceState.getRotationTouchHelper()
|
||||
.onEndTargetCalculated(mGestureState.getEndTarget(),
|
||||
mActivityInterface);
|
||||
|
||||
mRecentsView.onGestureEndTargetCalculated(mGestureState.getEndTarget());
|
||||
});
|
||||
() -> mDeviceState.getRotationTouchHelper().
|
||||
onEndTargetCalculated(mGestureState.getEndTarget(),
|
||||
mActivityInterface));
|
||||
|
||||
notifyGestureStartedAsync();
|
||||
}
|
||||
|
@ -741,6 +741,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<?>, Q extends
|
|||
public void onGestureCancelled() {
|
||||
updateDisplacement(0);
|
||||
mStateCallback.setStateOnUiThread(STATE_GESTURE_COMPLETED);
|
||||
mLogAction = Touch.SWIPE_NOOP;
|
||||
handleNormalGestureEnd(0, false, new PointF(), true /* isCancel */);
|
||||
}
|
||||
|
||||
|
@ -756,11 +757,13 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<?>, Q extends
|
|||
boolean isFling = mGestureStarted && !mIsMotionPaused
|
||||
&& Math.abs(endVelocity) > flingThreshold;
|
||||
mStateCallback.setStateOnUiThread(STATE_GESTURE_COMPLETED);
|
||||
|
||||
mLogAction = isFling ? Touch.FLING : Touch.SWIPE;
|
||||
boolean isVelocityVertical = Math.abs(velocity.y) > Math.abs(velocity.x);
|
||||
if (isVelocityVertical) {
|
||||
mLogDirectionUpOrLeft = velocity.y < 0;
|
||||
mLogDirection = velocity.y < 0 ? Direction.UP : Direction.DOWN;
|
||||
} else {
|
||||
mLogDirectionUpOrLeft = velocity.x < 0;
|
||||
mLogDirection = velocity.x < 0 ? Direction.LEFT : Direction.RIGHT;
|
||||
}
|
||||
mDownPos = downPos;
|
||||
handleNormalGestureEnd(endVelocity, isFling, velocity, false /* isCancel */);
|
||||
|
@ -972,7 +975,8 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<?>, Q extends
|
|||
break;
|
||||
case LAST_TASK:
|
||||
case NEW_TASK:
|
||||
event = mLogDirectionUpOrLeft ? LAUNCHER_QUICKSWITCH_LEFT
|
||||
event = (mLogDirection == Direction.LEFT)
|
||||
? LAUNCHER_QUICKSWITCH_LEFT
|
||||
: LAUNCHER_QUICKSWITCH_RIGHT;
|
||||
break;
|
||||
default:
|
||||
|
@ -980,10 +984,12 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<?>, Q extends
|
|||
}
|
||||
StatsLogger logger = StatsLogManager.newInstance(mContext).logger()
|
||||
.withSrcState(LAUNCHER_STATE_BACKGROUND)
|
||||
.withDstState(endTarget.containerType);
|
||||
.withDstState(StatsLogManager.containerTypeToAtomState(endTarget.containerType));
|
||||
if (targetTask != null) {
|
||||
logger.withItemInfo(targetTask.getItemInfo());
|
||||
}
|
||||
logger.log(event);
|
||||
|
||||
|
||||
DeviceProfile dp = mDp;
|
||||
if (dp == null || mDownPos == null) {
|
||||
|
@ -993,8 +999,12 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<?>, Q extends
|
|||
int pageIndex = endTarget == LAST_TASK
|
||||
? LOG_NO_OP_PAGE_INDEX
|
||||
: mRecentsView.getNextPage();
|
||||
// TODO: set correct container using the pageIndex
|
||||
logger.log(event);
|
||||
UserEventDispatcher.newInstance(mContext).logStateChangeAction(
|
||||
mLogAction, mLogDirection,
|
||||
(int) mDownPos.x, (int) mDownPos.y,
|
||||
ContainerType.NAVBAR, ContainerType.APP,
|
||||
endTarget.containerType,
|
||||
pageIndex);
|
||||
}
|
||||
|
||||
/** Animates to the given progress, where 0 is the current app and 1 is overview. */
|
||||
|
@ -1131,12 +1141,10 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<?>, Q extends
|
|||
anim.addOnUpdateListener((r, p) -> {
|
||||
updateSysUiFlags(Math.max(p, mCurrentShift.value));
|
||||
});
|
||||
final int cuj = InteractionJankMonitorWrapper.CUJ_APP_CLOSE_TO_HOME;
|
||||
anim.addAnimatorListener(new AnimationSuccessListener() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
Trace.beginAsyncSection(TRANSITION_OPEN_LAUNCHER, 0);
|
||||
InteractionJankMonitorWrapper.begin(cuj);
|
||||
if (mActivity != null) {
|
||||
removeLiveTileOverlay();
|
||||
}
|
||||
|
@ -1150,13 +1158,6 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<?>, Q extends
|
|||
// Make sure recents is in its final state
|
||||
maybeUpdateRecentsAttachedState(false);
|
||||
mActivityInterface.onSwipeUpToHomeComplete(mDeviceState);
|
||||
InteractionJankMonitorWrapper.end(cuj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationCancel(Animator animation) {
|
||||
super.onAnimationCancel(animation);
|
||||
InteractionJankMonitorWrapper.cancel(cuj);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -152,6 +152,11 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
|
|||
public abstract void onExitOverview(RotationTouchHelper deviceState,
|
||||
Runnable exitRunnable);
|
||||
|
||||
/**
|
||||
* Used for containerType in {@link com.android.launcher3.logging.UserEventDispatcher}
|
||||
*/
|
||||
public abstract int getContainerType();
|
||||
|
||||
public abstract boolean isInLiveTileMode();
|
||||
|
||||
public abstract void onLaunchTaskFailed();
|
||||
|
|
|
@ -28,6 +28,7 @@ import androidx.annotation.Nullable;
|
|||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.touch.PagedOrientationHandler;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||
import com.android.quickstep.fallback.RecentsState;
|
||||
import com.android.quickstep.util.ActivityInitListener;
|
||||
import com.android.quickstep.util.AnimatorControllerWithResistance;
|
||||
|
@ -143,6 +144,15 @@ public final class FallbackActivityInterface extends
|
|||
// no-op, fake landscape not supported for 3P
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getContainerType() {
|
||||
RecentsActivity activity = getCreatedActivity();
|
||||
boolean visible = activity != null && activity.isStarted() && activity.hasWindowFocus();
|
||||
return visible
|
||||
? LauncherLogProto.ContainerType.OTHER_LAUNCHER_APP
|
||||
: LauncherLogProto.ContainerType.APP;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInLiveTileMode() {
|
||||
return false;
|
||||
|
|
|
@ -15,9 +15,6 @@
|
|||
*/
|
||||
package com.android.quickstep;
|
||||
|
||||
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_BACKGROUND;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_HOME;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_OVERVIEW;
|
||||
import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
|
@ -26,6 +23,7 @@ import android.content.Intent;
|
|||
import android.os.Build;
|
||||
|
||||
import com.android.launcher3.statemanager.StatefulActivity;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
||||
import com.android.quickstep.util.ActiveGestureLog;
|
||||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
|
||||
|
@ -46,13 +44,13 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL
|
|||
* Defines the end targets of a gesture and the associated state.
|
||||
*/
|
||||
public enum GestureEndTarget {
|
||||
HOME(true, LAUNCHER_STATE_HOME, false),
|
||||
HOME(true, ContainerType.WORKSPACE, false),
|
||||
|
||||
RECENTS(true, LAUNCHER_STATE_OVERVIEW, true),
|
||||
RECENTS(true, ContainerType.TASKSWITCHER, true),
|
||||
|
||||
NEW_TASK(false, LAUNCHER_STATE_BACKGROUND, true),
|
||||
NEW_TASK(false, ContainerType.APP, true),
|
||||
|
||||
LAST_TASK(false, LAUNCHER_STATE_BACKGROUND, true);
|
||||
LAST_TASK(false, ContainerType.APP, true);
|
||||
|
||||
GestureEndTarget(boolean isLauncher, int containerType,
|
||||
boolean recentsAttachedToAppWindow) {
|
||||
|
|
|
@ -44,6 +44,7 @@ import com.android.launcher3.statehandlers.DepthController.ClampedDepthProperty;
|
|||
import com.android.launcher3.statemanager.StateManager;
|
||||
import com.android.launcher3.testing.TestProtocol;
|
||||
import com.android.launcher3.touch.PagedOrientationHandler;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||
import com.android.quickstep.SysUINavigationMode.Mode;
|
||||
import com.android.quickstep.util.ActivityInitListener;
|
||||
import com.android.quickstep.util.AnimatorControllerWithResistance;
|
||||
|
@ -207,6 +208,10 @@ public final class LauncherActivityInterface extends
|
|||
return false;
|
||||
}
|
||||
|
||||
launcher.getUserEventDispatcher().logActionCommand(
|
||||
LauncherLogProto.Action.Command.RECENTS_BUTTON,
|
||||
getContainerType(),
|
||||
LauncherLogProto.ContainerType.TASKSWITCHER);
|
||||
launcher.getStateManager().goToState(OVERVIEW,
|
||||
launcher.getStateManager().shouldAnimateStateChange(), onCompleteCallback);
|
||||
return true;
|
||||
|
@ -247,6 +252,13 @@ public final class LauncherActivityInterface extends
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getContainerType() {
|
||||
final Launcher launcher = getVisibleLauncher();
|
||||
return launcher != null ? launcher.getStateManager().getState().containerType
|
||||
: LauncherLogProto.ContainerType.APP;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInLiveTileMode() {
|
||||
Launcher launcher = getCreatedActivity();
|
||||
|
|
|
@ -30,6 +30,7 @@ import android.view.ViewConfiguration;
|
|||
import androidx.annotation.BinderThread;
|
||||
|
||||
import com.android.launcher3.statemanager.StatefulActivity;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||
import com.android.quickstep.util.ActivityInitListener;
|
||||
import com.android.quickstep.util.RemoteAnimationProvider;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
|
@ -46,6 +47,7 @@ public class OverviewCommandHelper {
|
|||
|
||||
private final Context mContext;
|
||||
private final RecentsAnimationDeviceState mDeviceState;
|
||||
private final RecentsModel mRecentsModel;
|
||||
private final OverviewComponentObserver mOverviewComponentObserver;
|
||||
|
||||
private long mLastToggleTime;
|
||||
|
@ -54,6 +56,7 @@ public class OverviewCommandHelper {
|
|||
OverviewComponentObserver observer) {
|
||||
mContext = context;
|
||||
mDeviceState = deviceState;
|
||||
mRecentsModel = RecentsModel.INSTANCE.get(mContext);
|
||||
mOverviewComponentObserver = observer;
|
||||
}
|
||||
|
||||
|
@ -147,6 +150,7 @@ public class OverviewCommandHelper {
|
|||
private final AppToOverviewAnimationProvider<T> mAnimationProvider;
|
||||
|
||||
private final long mToggleClickedTime = SystemClock.uptimeMillis();
|
||||
private boolean mUserEventLogged;
|
||||
private ActivityInitListener mListener;
|
||||
|
||||
public RecentsActivityCommand() {
|
||||
|
@ -156,7 +160,7 @@ public class OverviewCommandHelper {
|
|||
ActivityManagerWrapper.getInstance().getRunningTask(), mDeviceState);
|
||||
|
||||
// Preload the plan
|
||||
RecentsModel.INSTANCE.get(mContext).getTasks(null);
|
||||
mRecentsModel.getTasks(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -208,6 +212,13 @@ public class OverviewCommandHelper {
|
|||
|
||||
private boolean onActivityReady(Boolean wasVisible) {
|
||||
final T activity = mActivityInterface.getCreatedActivity();
|
||||
if (!mUserEventLogged) {
|
||||
activity.getUserEventDispatcher().logActionCommand(
|
||||
LauncherLogProto.Action.Command.RECENTS_BUTTON,
|
||||
mActivityInterface.getContainerType(),
|
||||
LauncherLogProto.ContainerType.TASKSWITCHER);
|
||||
mUserEventLogged = true;
|
||||
}
|
||||
return mAnimationProvider.onActivityReady(activity, wasVisible);
|
||||
}
|
||||
|
||||
|
|
|
@ -41,10 +41,7 @@ import com.android.launcher3.AbstractFloatingView;
|
|||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.InvariantDeviceProfile;
|
||||
import com.android.launcher3.LauncherAnimationRunner;
|
||||
import com.android.launcher3.LauncherAnimationRunner.AnimationResult;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.WrappedAnimationRunnerImpl;
|
||||
import com.android.launcher3.WrappedLauncherAnimationRunner;
|
||||
import com.android.launcher3.anim.Interpolators;
|
||||
import com.android.launcher3.anim.PendingAnimation;
|
||||
import com.android.launcher3.compat.AccessibilityManagerCompat;
|
||||
|
@ -90,9 +87,6 @@ public final class RecentsActivity extends StatefulActivity<RecentsState> {
|
|||
|
||||
private StateManager<RecentsState> mStateManager;
|
||||
|
||||
// Strong refs to runners which are cleared when the activity is destroyed
|
||||
private WrappedAnimationRunnerImpl mActivityLaunchAnimationRunner;
|
||||
|
||||
/**
|
||||
* Init drag layer and overview panel views.
|
||||
*/
|
||||
|
@ -124,6 +118,7 @@ public final class RecentsActivity extends StatefulActivity<RecentsState> {
|
|||
* etc.)
|
||||
*/
|
||||
protected void onHandleConfigChanged() {
|
||||
mUserEventDispatcher = null;
|
||||
initDeviceProfile();
|
||||
|
||||
AbstractFloatingView.closeOpenViews(this, true,
|
||||
|
@ -175,11 +170,8 @@ public final class RecentsActivity extends StatefulActivity<RecentsState> {
|
|||
}
|
||||
|
||||
final TaskView taskView = (TaskView) v;
|
||||
mActivityLaunchAnimationRunner = new WrappedAnimationRunnerImpl() {
|
||||
@Override
|
||||
public Handler getHandler() {
|
||||
return mUiHandler;
|
||||
}
|
||||
RemoteAnimationRunnerCompat runner = new LauncherAnimationRunner(mUiHandler,
|
||||
true /* startAtFrontOfQueue */) {
|
||||
|
||||
@Override
|
||||
public void onCreateAnimation(RemoteAnimationTargetCompat[] appTargets,
|
||||
|
@ -190,10 +182,8 @@ public final class RecentsActivity extends StatefulActivity<RecentsState> {
|
|||
result.setAnimation(anim, RecentsActivity.this);
|
||||
}
|
||||
};
|
||||
final LauncherAnimationRunner wrapper = new WrappedLauncherAnimationRunner<>(
|
||||
mActivityLaunchAnimationRunner, true /* startAtFrontOfQueue */);
|
||||
return ActivityOptionsCompat.makeRemoteAnimation(new RemoteAnimationAdapterCompat(
|
||||
wrapper, RECENTS_LAUNCH_DURATION,
|
||||
runner, RECENTS_LAUNCH_DURATION,
|
||||
RECENTS_LAUNCH_DURATION - STATUS_BAR_TRANSITION_DURATION
|
||||
- STATUS_BAR_TRANSITION_PRE_DELAY));
|
||||
}
|
||||
|
@ -298,7 +288,6 @@ public final class RecentsActivity extends StatefulActivity<RecentsState> {
|
|||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
ACTIVITY_TRACKER.onActivityDestroyed(this);
|
||||
mActivityLaunchAnimationRunner = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -18,6 +18,7 @@ package com.android.quickstep;
|
|||
import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
|
||||
|
||||
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
|
||||
import static com.android.launcher3.util.Executors.createAndStartNewLooper;
|
||||
import static com.android.quickstep.TaskUtils.checkCurrentOrManagedUserId;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
|
@ -25,11 +26,11 @@ import android.app.ActivityManager;
|
|||
import android.content.ComponentCallbacks2;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.os.Looper;
|
||||
import android.os.Process;
|
||||
import android.os.UserHandle;
|
||||
|
||||
import com.android.launcher3.icons.IconProvider;
|
||||
import com.android.launcher3.util.Executors.SimpleThreadFactory;
|
||||
import com.android.launcher3.util.MainThreadInitializedObject;
|
||||
import com.android.systemui.shared.recents.model.Task;
|
||||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
|
@ -39,8 +40,6 @@ import com.android.systemui.shared.system.TaskStackChangeListener;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
|
@ -53,9 +52,6 @@ public class RecentsModel extends TaskStackChangeListener {
|
|||
public static final MainThreadInitializedObject<RecentsModel> INSTANCE =
|
||||
new MainThreadInitializedObject<>(RecentsModel::new);
|
||||
|
||||
private static final Executor RECENTS_MODEL_EXECUTOR = Executors.newSingleThreadExecutor(
|
||||
new SimpleThreadFactory("TaskThumbnailIconCache-", THREAD_PRIORITY_BACKGROUND));
|
||||
|
||||
private final List<TaskVisualsChangeListener> mThumbnailChangeListeners = new ArrayList<>();
|
||||
private final Context mContext;
|
||||
|
||||
|
@ -65,10 +61,12 @@ public class RecentsModel extends TaskStackChangeListener {
|
|||
|
||||
private RecentsModel(Context context) {
|
||||
mContext = context;
|
||||
Looper looper =
|
||||
createAndStartNewLooper("TaskThumbnailIconCache", THREAD_PRIORITY_BACKGROUND);
|
||||
mTaskList = new RecentTasksList(MAIN_EXECUTOR,
|
||||
new KeyguardManagerCompat(context), ActivityManagerWrapper.getInstance());
|
||||
mIconCache = new TaskIconCache(context, RECENTS_MODEL_EXECUTOR);
|
||||
mThumbnailCache = new TaskThumbnailCache(context, RECENTS_MODEL_EXECUTOR);
|
||||
mIconCache = new TaskIconCache(context, looper);
|
||||
mThumbnailCache = new TaskThumbnailCache(context, looper);
|
||||
|
||||
ActivityManagerWrapper.getInstance().registerTaskStackListener(this);
|
||||
IconProvider.registerIconChangeListener(context,
|
||||
|
|
|
@ -17,6 +17,7 @@ package com.android.quickstep;
|
|||
|
||||
import static com.android.launcher3.FastBitmapDrawable.newIcon;
|
||||
import static com.android.launcher3.uioverrides.QuickstepLauncher.GO_LOW_RAM_RECENTS_ENABLED;
|
||||
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
|
||||
|
||||
import android.app.ActivityManager.TaskDescription;
|
||||
import android.content.Context;
|
||||
|
@ -26,6 +27,8 @@ import android.graphics.Bitmap;
|
|||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.UserHandle;
|
||||
import android.util.SparseArray;
|
||||
import android.view.accessibility.AccessibilityManager;
|
||||
|
@ -34,11 +37,12 @@ import androidx.annotation.WorkerThread;
|
|||
|
||||
import com.android.launcher3.FastBitmapDrawable;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.icons.BitmapInfo;
|
||||
import com.android.launcher3.icons.IconProvider;
|
||||
import com.android.launcher3.icons.LauncherIcons;
|
||||
import com.android.launcher3.icons.cache.HandlerRunnable;
|
||||
import com.android.launcher3.util.Preconditions;
|
||||
import com.android.quickstep.util.CancellableTask;
|
||||
import com.android.quickstep.util.TaskKeyLruCache;
|
||||
import com.android.systemui.shared.recents.model.Task;
|
||||
import com.android.systemui.shared.recents.model.Task.TaskKey;
|
||||
|
@ -46,7 +50,6 @@ import com.android.systemui.shared.system.ActivityManagerWrapper;
|
|||
import com.android.systemui.shared.system.PackageManagerWrapper;
|
||||
import com.android.systemui.shared.system.TaskDescriptionCompat;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
|
@ -54,7 +57,7 @@ import java.util.function.Consumer;
|
|||
*/
|
||||
public class TaskIconCache {
|
||||
|
||||
private final Executor mBgExecutor;
|
||||
private final Handler mBackgroundHandler;
|
||||
private final AccessibilityManager mAccessibilityManager;
|
||||
|
||||
private final Context mContext;
|
||||
|
@ -62,9 +65,9 @@ public class TaskIconCache {
|
|||
private final SparseArray<BitmapInfo> mDefaultIcons = new SparseArray<>();
|
||||
private final IconProvider mIconProvider;
|
||||
|
||||
public TaskIconCache(Context context, Executor bgExecutor) {
|
||||
public TaskIconCache(Context context, Looper backgroundLooper) {
|
||||
mContext = context;
|
||||
mBgExecutor = bgExecutor;
|
||||
mBackgroundHandler = new Handler(backgroundLooper);
|
||||
mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
|
||||
|
||||
Resources res = context.getResources();
|
||||
|
@ -80,27 +83,31 @@ public class TaskIconCache {
|
|||
* @param callback The callback to receive the task after its data has been populated.
|
||||
* @return A cancelable handle to the request
|
||||
*/
|
||||
public CancellableTask updateIconInBackground(Task task, Consumer<Task> callback) {
|
||||
public IconLoadRequest updateIconInBackground(Task task, Consumer<Task> callback) {
|
||||
Preconditions.assertUIThread();
|
||||
if (task.icon != null) {
|
||||
// Nothing to load, the icon is already loaded
|
||||
callback.accept(task);
|
||||
return null;
|
||||
}
|
||||
CancellableTask<TaskCacheEntry> request = new CancellableTask<TaskCacheEntry>() {
|
||||
@Override
|
||||
public TaskCacheEntry getResultOnBg() {
|
||||
return getCacheEntry(task);
|
||||
}
|
||||
|
||||
IconLoadRequest request = new IconLoadRequest(mBackgroundHandler) {
|
||||
@Override
|
||||
public void handleResult(TaskCacheEntry result) {
|
||||
task.icon = result.icon;
|
||||
task.titleDescription = result.contentDescription;
|
||||
callback.accept(task);
|
||||
public void run() {
|
||||
TaskCacheEntry entry = getCacheEntry(task);
|
||||
if (isCanceled()) {
|
||||
// We don't call back to the provided callback in this case
|
||||
return;
|
||||
}
|
||||
MAIN_EXECUTOR.execute(() -> {
|
||||
task.icon = entry.icon;
|
||||
task.titleDescription = entry.contentDescription;
|
||||
callback.accept(task);
|
||||
onEnd();
|
||||
});
|
||||
}
|
||||
};
|
||||
mBgExecutor.execute(request);
|
||||
Utilities.postAsyncCallback(mBackgroundHandler, request);
|
||||
return request;
|
||||
}
|
||||
|
||||
|
@ -113,8 +120,9 @@ public class TaskIconCache {
|
|||
}
|
||||
|
||||
void invalidateCacheEntries(String pkg, UserHandle handle) {
|
||||
mBgExecutor.execute(() -> mIconCache.removeAll(key ->
|
||||
pkg.equals(key.getPackageName()) && handle.getIdentifier() == key.userId));
|
||||
Utilities.postAsyncCallback(mBackgroundHandler,
|
||||
() -> mIconCache.removeAll(key ->
|
||||
pkg.equals(key.getPackageName()) && handle.getIdentifier() == key.userId));
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
|
@ -200,6 +208,12 @@ public class TaskIconCache {
|
|||
}
|
||||
}
|
||||
|
||||
public static abstract class IconLoadRequest extends HandlerRunnable {
|
||||
IconLoadRequest(Handler handler) {
|
||||
super(handler, null);
|
||||
}
|
||||
}
|
||||
|
||||
private static class TaskCacheEntry {
|
||||
public Drawable icon;
|
||||
public String contentDescription = "";
|
||||
|
|
|
@ -21,6 +21,7 @@ import static android.view.Display.DEFAULT_DISPLAY;
|
|||
import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_SELECTIONS;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_FREE_FORM_TAP;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_SPLIT_SCREEN_TAP;
|
||||
import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch.TAP;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.ActivityOptions;
|
||||
|
@ -38,6 +39,7 @@ import com.android.launcher3.logging.StatsLogManager.LauncherEvent;
|
|||
import com.android.launcher3.model.WellbeingModel;
|
||||
import com.android.launcher3.popup.SystemShortcut;
|
||||
import com.android.launcher3.popup.SystemShortcut.AppInfo;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||
import com.android.launcher3.util.Executors;
|
||||
import com.android.launcher3.util.InstantAppResolver;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
|
@ -226,6 +228,8 @@ public interface TaskShortcutFactory {
|
|||
|
||||
@Override
|
||||
protected boolean onActivityStarted(BaseDraggingActivity activity) {
|
||||
activity.getUserEventDispatcher().logActionOnControl(TAP,
|
||||
LauncherLogProto.ControlType.SPLIT_SCREEN_TARGET);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -15,12 +15,17 @@
|
|||
*/
|
||||
package com.android.quickstep;
|
||||
|
||||
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.icons.cache.HandlerRunnable;
|
||||
import com.android.launcher3.util.Preconditions;
|
||||
import com.android.quickstep.util.CancellableTask;
|
||||
import com.android.quickstep.util.TaskKeyLruCache;
|
||||
import com.android.systemui.shared.recents.model.Task;
|
||||
import com.android.systemui.shared.recents.model.Task.TaskKey;
|
||||
|
@ -28,12 +33,11 @@ import com.android.systemui.shared.recents.model.ThumbnailData;
|
|||
import com.android.systemui.shared.system.ActivityManagerWrapper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class TaskThumbnailCache {
|
||||
|
||||
private final Executor mBgExecutor;
|
||||
private final Handler mBackgroundHandler;
|
||||
|
||||
private final int mCacheSize;
|
||||
private final TaskKeyLruCache<ThumbnailData> mCache;
|
||||
|
@ -90,8 +94,8 @@ public class TaskThumbnailCache {
|
|||
}
|
||||
}
|
||||
|
||||
public TaskThumbnailCache(Context context, Executor bgExecutor) {
|
||||
mBgExecutor = bgExecutor;
|
||||
public TaskThumbnailCache(Context context, Looper backgroundLooper) {
|
||||
mBackgroundHandler = new Handler(backgroundLooper);
|
||||
mHighResLoadingState = new HighResLoadingState(context);
|
||||
|
||||
Resources res = context.getResources();
|
||||
|
@ -126,7 +130,7 @@ public class TaskThumbnailCache {
|
|||
* @param callback The callback to receive the task after its data has been populated.
|
||||
* @return A cancelable handle to the request
|
||||
*/
|
||||
public CancellableTask updateThumbnailInBackground(
|
||||
public ThumbnailLoadRequest updateThumbnailInBackground(
|
||||
Task task, Consumer<ThumbnailData> callback) {
|
||||
Preconditions.assertUIThread();
|
||||
|
||||
|
@ -138,13 +142,14 @@ public class TaskThumbnailCache {
|
|||
return null;
|
||||
}
|
||||
|
||||
|
||||
return updateThumbnailInBackground(task.key, !mHighResLoadingState.isEnabled(), t -> {
|
||||
task.thumbnail = t;
|
||||
callback.accept(t);
|
||||
});
|
||||
}
|
||||
|
||||
private CancellableTask updateThumbnailInBackground(TaskKey key, boolean lowResolution,
|
||||
private ThumbnailLoadRequest updateThumbnailInBackground(TaskKey key, boolean lowResolution,
|
||||
Consumer<ThumbnailData> callback) {
|
||||
Preconditions.assertUIThread();
|
||||
|
||||
|
@ -155,20 +160,26 @@ public class TaskThumbnailCache {
|
|||
return null;
|
||||
}
|
||||
|
||||
CancellableTask<ThumbnailData> request = new CancellableTask<ThumbnailData>() {
|
||||
ThumbnailLoadRequest request = new ThumbnailLoadRequest(mBackgroundHandler,
|
||||
lowResolution) {
|
||||
@Override
|
||||
public ThumbnailData getResultOnBg() {
|
||||
return ActivityManagerWrapper.getInstance().getTaskThumbnail(
|
||||
public void run() {
|
||||
ThumbnailData thumbnail = ActivityManagerWrapper.getInstance().getTaskThumbnail(
|
||||
key.id, lowResolution);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleResult(ThumbnailData result) {
|
||||
mCache.put(key, result);
|
||||
callback.accept(result);
|
||||
MAIN_EXECUTOR.execute(() -> {
|
||||
if (isCanceled()) {
|
||||
// We don't call back to the provided callback in this case
|
||||
return;
|
||||
}
|
||||
|
||||
mCache.put(key, thumbnail);
|
||||
callback.accept(thumbnail);
|
||||
onEnd();
|
||||
});
|
||||
}
|
||||
};
|
||||
mBgExecutor.execute(request);
|
||||
Utilities.postAsyncCallback(mBackgroundHandler, request);
|
||||
return request;
|
||||
}
|
||||
|
||||
|
@ -207,6 +218,15 @@ public class TaskThumbnailCache {
|
|||
return mEnableTaskSnapshotPreloading && mHighResLoadingState.mVisible;
|
||||
}
|
||||
|
||||
public static abstract class ThumbnailLoadRequest extends HandlerRunnable {
|
||||
public final boolean mLowResolution;
|
||||
|
||||
ThumbnailLoadRequest(Handler handler, boolean lowResolution) {
|
||||
super(handler, null);
|
||||
mLowResolution = lowResolution;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Whether device supports low-res thumbnails. Low-res files are an optimization
|
||||
* for faster load times of snapshots. Devices can optionally disable low-res files so that
|
||||
|
|
|
@ -20,7 +20,6 @@ import static android.view.MotionEvent.ACTION_CANCEL;
|
|||
import static android.view.MotionEvent.ACTION_DOWN;
|
||||
import static android.view.MotionEvent.ACTION_UP;
|
||||
|
||||
import static com.android.launcher3.config.FeatureFlags.ASSISTANT_GIVES_LAUNCHER_FOCUS;
|
||||
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
|
||||
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
|
||||
import static com.android.quickstep.GestureState.DEFAULT_STATE;
|
||||
|
@ -688,7 +687,7 @@ public class TouchInteractionService extends Service implements PluginListener<O
|
|||
final boolean disableHorizontalSwipe = mDeviceState.isInExclusionRegion(event);
|
||||
return new OtherActivityInputConsumer(this, mDeviceState, mTaskAnimationManager,
|
||||
gestureState, shouldDefer, this::onConsumerInactive,
|
||||
mInputMonitorCompat, mInputEventReceiver, disableHorizontalSwipe, factory);
|
||||
mInputMonitorCompat, disableHorizontalSwipe, factory);
|
||||
}
|
||||
|
||||
private InputConsumer createDeviceLockedInputConsumer(GestureState gestureState) {
|
||||
|
@ -710,10 +709,8 @@ public class TouchInteractionService extends Service implements PluginListener<O
|
|||
|
||||
if (activity.getRootView().hasWindowFocus()
|
||||
|| previousGestureState.isRunningAnimationToLauncher()
|
||||
|| (ASSISTANT_GIVES_LAUNCHER_FOCUS.get()
|
||||
&& forceOverviewInputConsumer)
|
||||
|| (ENABLE_QUICKSTEP_LIVE_TILE.get())
|
||||
&& gestureState.getActivityInterface().isInLiveTileMode()) {
|
||||
|| (FeatureFlags.ASSISTANT_GIVES_LAUNCHER_FOCUS.get()
|
||||
&& forceOverviewInputConsumer)) {
|
||||
return new OverviewInputConsumer(gestureState, activity, mInputMonitorCompat,
|
||||
false /* startingInActivityBounds */);
|
||||
} else {
|
||||
|
@ -737,8 +734,6 @@ public class TouchInteractionService extends Service implements PluginListener<O
|
|||
private void reset() {
|
||||
mConsumer = mUncheckedConsumer = mResetGestureInputConsumer;
|
||||
mGestureState = DEFAULT_STATE;
|
||||
// By default, use batching of the input events
|
||||
mInputEventReceiver.setBatchingEnabled(true);
|
||||
}
|
||||
|
||||
private void preloadOverview(boolean fromInit) {
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
*/
|
||||
package com.android.quickstep.fallback;
|
||||
|
||||
import static com.android.quickstep.GestureState.GestureEndTarget.RECENTS;
|
||||
import static com.android.quickstep.fallback.RecentsState.DEFAULT;
|
||||
import static com.android.quickstep.fallback.RecentsState.MODAL_TASK;
|
||||
|
||||
|
@ -28,7 +27,6 @@ import android.util.AttributeSet;
|
|||
import com.android.launcher3.anim.PendingAnimation;
|
||||
import com.android.launcher3.statemanager.StateManager.StateListener;
|
||||
import com.android.quickstep.FallbackActivityInterface;
|
||||
import com.android.quickstep.GestureState;
|
||||
import com.android.quickstep.RecentsActivity;
|
||||
import com.android.quickstep.views.OverviewActionsView;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
|
@ -76,14 +74,14 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity>
|
|||
}
|
||||
|
||||
/**
|
||||
* When the gesture ends and we're going to recents view, we also remove the temporary
|
||||
* When the gesture ends and recents view become interactive, we also remove the temporary
|
||||
* invisible tile added for the home task. This also pushes the remaining tiles back
|
||||
* to the center.
|
||||
*/
|
||||
@Override
|
||||
public void onGestureEndTargetCalculated(GestureState.GestureEndTarget endTarget) {
|
||||
super.onGestureEndTargetCalculated(endTarget);
|
||||
if (mHomeTaskInfo != null && endTarget == RECENTS) {
|
||||
public void onGestureAnimationEnd() {
|
||||
super.onGestureAnimationEnd();
|
||||
if (mHomeTaskInfo != null) {
|
||||
TaskView tv = getTaskView(mHomeTaskInfo.taskId);
|
||||
if (tv != null) {
|
||||
PendingAnimation pa = createTaskDismissAnimation(tv, true, false, 150);
|
||||
|
|
|
@ -25,6 +25,12 @@ import static android.view.MotionEvent.ACTION_POINTER_UP;
|
|||
import static android.view.MotionEvent.ACTION_UP;
|
||||
|
||||
import static com.android.launcher3.Utilities.squaredHypot;
|
||||
import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction.UPLEFT;
|
||||
import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction.UPRIGHT;
|
||||
import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch.FLING;
|
||||
import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch.SWIPE;
|
||||
import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch.SWIPE_NOOP;
|
||||
import static com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType.NAVBAR;
|
||||
|
||||
import android.animation.ValueAnimator;
|
||||
import android.content.Context;
|
||||
|
@ -41,6 +47,7 @@ import android.view.ViewConfiguration;
|
|||
import com.android.launcher3.BaseDraggingActivity;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.anim.Interpolators;
|
||||
import com.android.launcher3.logging.UserEventDispatcher;
|
||||
import com.android.quickstep.BaseActivityInterface;
|
||||
import com.android.quickstep.GestureState;
|
||||
import com.android.quickstep.InputConsumer;
|
||||
|
@ -73,6 +80,7 @@ public class AssistantInputConsumer extends DelegateInputConsumer {
|
|||
private float mTimeFraction;
|
||||
private long mDragTime;
|
||||
private float mLastProgress;
|
||||
private int mDirection;
|
||||
private BaseActivityInterface mActivityInterface;
|
||||
|
||||
private final float mDragDistThreshold;
|
||||
|
@ -189,6 +197,8 @@ public class AssistantInputConsumer extends DelegateInputConsumer {
|
|||
if (mState != STATE_DELEGATE_ACTIVE && !mLaunchedAssistant) {
|
||||
ValueAnimator animator = ValueAnimator.ofFloat(mLastProgress, 0)
|
||||
.setDuration(RETRACT_ANIMATION_DURATION_MS);
|
||||
UserEventDispatcher.newInstance(mContext).logActionOnContainer(
|
||||
SWIPE_NOOP, mDirection, NAVBAR);
|
||||
animator.addUpdateListener(valueAnimator -> {
|
||||
float progress = (float) valueAnimator.getAnimatedValue();
|
||||
SystemUiProxy.INSTANCE.get(mContext).onAssistantProgress(progress);
|
||||
|
@ -213,7 +223,7 @@ public class AssistantInputConsumer extends DelegateInputConsumer {
|
|||
mLastProgress = Math.min(mDistance * 1f / mDragDistThreshold, 1) * mTimeFraction;
|
||||
if (mDistance >= mDragDistThreshold && mTimeFraction >= 1) {
|
||||
SystemUiProxy.INSTANCE.get(mContext).onAssistantGestureCompletion(0);
|
||||
startAssistantInternal();
|
||||
startAssistantInternal(SWIPE);
|
||||
|
||||
Bundle args = new Bundle();
|
||||
args.putInt(OPA_BUNDLE_TRIGGER, OPA_BUNDLE_TRIGGER_DIAG_SWIPE_GESTURE);
|
||||
|
@ -226,7 +236,10 @@ public class AssistantInputConsumer extends DelegateInputConsumer {
|
|||
}
|
||||
}
|
||||
|
||||
private void startAssistantInternal() {
|
||||
private void startAssistantInternal(int gestureType) {
|
||||
UserEventDispatcher.newInstance(mContext)
|
||||
.logActionOnContainer(gestureType, mDirection, NAVBAR);
|
||||
|
||||
BaseDraggingActivity launcherActivity = mActivityInterface.getCreatedActivity();
|
||||
if (launcherActivity != null) {
|
||||
launcherActivity.getRootView().performHapticFeedback(
|
||||
|
@ -240,6 +253,7 @@ public class AssistantInputConsumer extends DelegateInputConsumer {
|
|||
*/
|
||||
private boolean isValidAssistantGestureAngle(float deltaX, float deltaY) {
|
||||
float angle = (float) Math.toDegrees(Math.atan2(deltaY, deltaX));
|
||||
mDirection = angle > 90 ? UPLEFT : UPRIGHT;
|
||||
|
||||
// normalize so that angle is measured clockwise from horizontal in the bottom right corner
|
||||
// and counterclockwise from horizontal in the bottom left corner
|
||||
|
@ -258,7 +272,7 @@ public class AssistantInputConsumer extends DelegateInputConsumer {
|
|||
mLastProgress = 1;
|
||||
SystemUiProxy.INSTANCE.get(mContext).onAssistantGestureCompletion(
|
||||
(float) Math.sqrt(velocityX * velocityX + velocityY * velocityY));
|
||||
startAssistantInternal();
|
||||
startAssistantInternal(FLING);
|
||||
|
||||
Bundle args = new Bundle();
|
||||
args.putInt(INVOCATION_TYPE_KEY, INVOCATION_TYPE_GESTURE);
|
||||
|
|
|
@ -67,7 +67,6 @@ import com.android.quickstep.util.CachedEventDispatcher;
|
|||
import com.android.quickstep.util.MotionPauseDetector;
|
||||
import com.android.quickstep.util.NavBarPosition;
|
||||
import com.android.systemui.shared.system.ActivityManagerWrapper;
|
||||
import com.android.systemui.shared.system.InputChannelCompat.InputEventReceiver;
|
||||
import com.android.systemui.shared.system.InputMonitorCompat;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
@ -93,7 +92,6 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
|||
private RecentsAnimationCallbacks mActiveCallbacks;
|
||||
private final CachedEventDispatcher mRecentsViewDispatcher = new CachedEventDispatcher();
|
||||
private final InputMonitorCompat mInputMonitorCompat;
|
||||
private final InputEventReceiver mInputEventReceiver;
|
||||
private final BaseActivityInterface mActivityInterface;
|
||||
|
||||
private final AbsSwipeUpHandler.Factory mHandlerFactory;
|
||||
|
@ -137,8 +135,8 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
|||
public OtherActivityInputConsumer(Context base, RecentsAnimationDeviceState deviceState,
|
||||
TaskAnimationManager taskAnimationManager, GestureState gestureState,
|
||||
boolean isDeferredDownTarget, Consumer<OtherActivityInputConsumer> onCompleteCallback,
|
||||
InputMonitorCompat inputMonitorCompat, InputEventReceiver inputEventReceiver,
|
||||
boolean disableHorizontalSwipe, Factory handlerFactory) {
|
||||
InputMonitorCompat inputMonitorCompat, boolean disableHorizontalSwipe,
|
||||
Factory handlerFactory) {
|
||||
super(base);
|
||||
mDeviceState = deviceState;
|
||||
mNavBarPosition = mDeviceState.getNavBarPosition();
|
||||
|
@ -156,7 +154,6 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
|||
mOnCompleteCallback = onCompleteCallback;
|
||||
mVelocityTracker = VelocityTracker.obtain();
|
||||
mInputMonitorCompat = inputMonitorCompat;
|
||||
mInputEventReceiver = inputEventReceiver;
|
||||
|
||||
boolean continuingPreviousGesture = mTaskAnimationManager.isRecentsAnimationRunning();
|
||||
mIsDeferredDownTarget = !continuingPreviousGesture && isDeferredDownTarget;
|
||||
|
@ -218,9 +215,6 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
|||
|
||||
switch (ev.getActionMasked()) {
|
||||
case ACTION_DOWN: {
|
||||
// Until we detect the gesture, handle events as we receive them
|
||||
mInputEventReceiver.setBatchingEnabled(false);
|
||||
|
||||
Object traceToken = TraceHelper.INSTANCE.beginSection(DOWN_EVT,
|
||||
FLAG_CHECK_FOR_RACE_CONDITIONS);
|
||||
mActivePointerId = ev.getPointerId(0);
|
||||
|
@ -357,8 +351,6 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
|||
}
|
||||
TestLogging.recordEvent(TestProtocol.SEQUENCE_PILFER, "pilferPointers");
|
||||
mInputMonitorCompat.pilferPointers();
|
||||
// Once we detect the gesture, we can enable batching to reduce further updates
|
||||
mInputEventReceiver.setBatchingEnabled(true);
|
||||
|
||||
mActivityInterface.closeOverlay();
|
||||
ActivityManagerWrapper.getInstance().closeSystemWindows(
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
*/
|
||||
package com.android.quickstep.inputconsumers;
|
||||
|
||||
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_BACKGROUND;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_HOME;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_HOME_GESTURE;
|
||||
|
||||
|
@ -28,6 +27,9 @@ import com.android.launcher3.BaseDraggingActivity;
|
|||
import com.android.launcher3.logger.LauncherAtom;
|
||||
import com.android.launcher3.testing.TestLogging;
|
||||
import com.android.launcher3.testing.TestProtocol;
|
||||
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.GestureState;
|
||||
import com.android.quickstep.InputConsumer;
|
||||
import com.android.quickstep.RecentsAnimationDeviceState;
|
||||
|
@ -80,12 +82,17 @@ public class OverviewWithoutFocusInputConsumer implements InputConsumer,
|
|||
mContext.startActivity(mGestureState.getHomeIntent());
|
||||
ActiveGestureLog.INSTANCE.addLog("startQuickstep");
|
||||
BaseActivity activity = BaseDraggingActivity.fromContext(mContext);
|
||||
int state = (mGestureState != null && mGestureState.getEndTarget() != null)
|
||||
int pageIndex = -1; // This number doesn't reflect workspace page index.
|
||||
// It only indicates that launcher client screen was shown.
|
||||
int containerType = (mGestureState != null && mGestureState.getEndTarget() != null)
|
||||
? mGestureState.getEndTarget().containerType
|
||||
: LAUNCHER_STATE_HOME;
|
||||
: LauncherLogProto.ContainerType.WORKSPACE;
|
||||
activity.getUserEventDispatcher().logActionOnContainer(
|
||||
wasFling ? Touch.FLING : Touch.SWIPE, Direction.UP, containerType, pageIndex);
|
||||
activity.getUserEventDispatcher().setPreviousHomeGesture(true);
|
||||
activity.getStatsLogManager().logger()
|
||||
.withSrcState(LAUNCHER_STATE_BACKGROUND)
|
||||
.withDstState(state)
|
||||
.withSrcState(LAUNCHER_STATE_HOME)
|
||||
.withDstState(LAUNCHER_STATE_HOME)
|
||||
.withContainerInfo(LauncherAtom.ContainerInfo.newBuilder()
|
||||
.setWorkspace(
|
||||
LauncherAtom.WorkspaceContainer.newBuilder()
|
||||
|
|
|
@ -24,7 +24,7 @@ import com.android.quickstep.interaction.TutorialController.TutorialType;
|
|||
/** Shows the Home gesture interactive tutorial. */
|
||||
public class AssistantGestureTutorialFragment extends TutorialFragment {
|
||||
@Override
|
||||
Integer getHandAnimationResId() {
|
||||
int getHandAnimationResId() {
|
||||
return R.drawable.assistant_gesture;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ import com.android.quickstep.interaction.TutorialController.TutorialType;
|
|||
/** Shows the Back gesture interactive tutorial. */
|
||||
public class BackGestureTutorialFragment extends TutorialFragment {
|
||||
@Override
|
||||
Integer getHandAnimationResId() {
|
||||
int getHandAnimationResId() {
|
||||
return R.drawable.back_gesture;
|
||||
}
|
||||
|
||||
|
|
|
@ -143,10 +143,6 @@ public class EdgeBackGestureHandler implements OnTouchListener {
|
|||
return false;
|
||||
}
|
||||
|
||||
boolean onInterceptTouch(MotionEvent motionEvent) {
|
||||
return isWithinTouchRegion((int) motionEvent.getX(), (int) motionEvent.getY());
|
||||
}
|
||||
|
||||
private boolean isWithinTouchRegion(int x, int y) {
|
||||
// Disallow if too far from the edge
|
||||
if (x > mEdgeWidth + mLeftInset && x < (mDisplaySize.x - mEdgeWidth - mRightInset)) {
|
||||
|
|
|
@ -21,7 +21,7 @@ import com.android.quickstep.interaction.TutorialController.TutorialType;
|
|||
/** Shows the Home gesture interactive tutorial. */
|
||||
public class HomeGestureTutorialFragment extends TutorialFragment {
|
||||
@Override
|
||||
Integer getHandAnimationResId() {
|
||||
int getHandAnimationResId() {
|
||||
return R.drawable.home_gesture;
|
||||
}
|
||||
|
||||
|
|
|
@ -250,12 +250,6 @@ public class NavBarGestureHandler implements OnTouchListener,
|
|||
return intercepted;
|
||||
}
|
||||
|
||||
boolean onInterceptTouch(MotionEvent event) {
|
||||
return mAssistantLeftRegion.contains(event.getX(), event.getY())
|
||||
|| mAssistantRightRegion.contains(event.getX(), event.getY())
|
||||
|| event.getY() >= mDisplaySize.y - mBottomGestureHeight;
|
||||
}
|
||||
|
||||
protected void onMotionPauseDetected() {
|
||||
VibratorWrapper.INSTANCE.get(mContext).vibrate(OVERVIEW_HAPTIC);
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ import com.android.quickstep.interaction.TutorialController.TutorialType;
|
|||
/** Shows the Overview gesture interactive tutorial. */
|
||||
public class OverviewGestureTutorialFragment extends TutorialFragment {
|
||||
@Override
|
||||
Integer getHandAnimationResId() {
|
||||
int getHandAnimationResId() {
|
||||
return R.drawable.overview_gesture;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,44 +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 com.android.quickstep.interaction;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.widget.RelativeLayout;
|
||||
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
/** Root layout that TutorialFragment uses to intercept motion events. */
|
||||
public class RootSandboxLayout extends RelativeLayout {
|
||||
public RootSandboxLayout(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public RootSandboxLayout(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public RootSandboxLayout(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onInterceptTouchEvent(MotionEvent motionEvent) {
|
||||
return ((TutorialFragment) FragmentManager.findFragment(this))
|
||||
.onInterceptTouch(motionEvent);
|
||||
}
|
||||
}
|
|
@ -1,44 +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 com.android.quickstep.interaction;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.launcher3.InvariantDeviceProfile;
|
||||
import com.android.launcher3.graphics.LauncherPreviewRenderer;
|
||||
|
||||
/** Renders a fake Launcher for use in the Sandbox. */
|
||||
class SandboxLauncherRenderer extends LauncherPreviewRenderer {
|
||||
SandboxLauncherRenderer(Context context, InvariantDeviceProfile idp, boolean migrated) {
|
||||
super(context, idp, migrated);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldShowRealLauncherPreview() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldShowQsb() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View.OnLongClickListener getWorkspaceChildOnLongClickListener() {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -1,102 +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 com.android.quickstep.interaction;
|
||||
|
||||
import android.graphics.PointF;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.R;
|
||||
import com.android.quickstep.interaction.EdgeBackGestureHandler.BackGestureResult;
|
||||
import com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestureResult;
|
||||
|
||||
/** A {@link TutorialController} for the Sandbox Mode. */
|
||||
public class SandboxModeTutorialController extends SwipeUpGestureTutorialController {
|
||||
|
||||
SandboxModeTutorialController(SandboxModeTutorialFragment fragment, TutorialType tutorialType) {
|
||||
super(fragment, tutorialType);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
Integer getTitleStringId() {
|
||||
return R.string.sandbox_mode_title;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
Integer getSubtitleStringId() {
|
||||
return R.string.sandbox_mode_subtitle;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
Integer getActionButtonStringId() {
|
||||
return R.string.gesture_tutorial_action_button_label_done;
|
||||
}
|
||||
|
||||
@Override
|
||||
void onActionButtonClicked(View button) {
|
||||
mTutorialFragment.closeTutorial();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackGestureAttempted(BackGestureResult result) {
|
||||
switch (result) {
|
||||
case BACK_COMPLETED_FROM_LEFT:
|
||||
case BACK_COMPLETED_FROM_RIGHT:
|
||||
showRippleEffect(null);
|
||||
showFeedback(R.string.sandbox_mode_back_gesture_feedback_successful);
|
||||
break;
|
||||
case BACK_CANCELLED_FROM_RIGHT:
|
||||
showFeedback(R.string.back_gesture_feedback_cancelled_right_edge);
|
||||
break;
|
||||
case BACK_CANCELLED_FROM_LEFT:
|
||||
showFeedback(R.string.back_gesture_feedback_cancelled_left_edge);
|
||||
break;
|
||||
case BACK_NOT_STARTED_TOO_FAR_FROM_EDGE:
|
||||
showFeedback(R.string.sandbox_mode_back_gesture_feedback_swipe_too_far_from_edge);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNavBarGestureAttempted(NavBarGestureResult result, PointF finalVelocity) {
|
||||
switch (result) {
|
||||
case ASSISTANT_COMPLETED:
|
||||
showRippleEffect(null);
|
||||
showFeedback(R.string.sandbox_mode_assistant_gesture_feedback_successful);
|
||||
break;
|
||||
case HOME_GESTURE_COMPLETED:
|
||||
animateFakeTaskViewHome(finalVelocity, () -> {
|
||||
showFeedback(R.string.sandbox_mode_home_gesture_feedback_successful);
|
||||
});
|
||||
break;
|
||||
case OVERVIEW_GESTURE_COMPLETED:
|
||||
fadeOutFakeTaskView(true, () -> {
|
||||
showFeedback(R.string.sandbox_mode_overview_gesture_feedback_successful);
|
||||
});
|
||||
break;
|
||||
case HOME_OR_OVERVIEW_NOT_STARTED_WRONG_SWIPE_DIRECTION:
|
||||
case HOME_OR_OVERVIEW_CANCELLED:
|
||||
case HOME_NOT_STARTED_TOO_FAR_FROM_EDGE:
|
||||
case OVERVIEW_NOT_STARTED_TOO_FAR_FROM_EDGE:
|
||||
showFeedback(R.string.home_gesture_feedback_swipe_too_far_from_edge);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,43 +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 com.android.quickstep.interaction;
|
||||
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.quickstep.interaction.TutorialController.TutorialType;
|
||||
|
||||
/** Shows the general navigation gesture sandbox environment. */
|
||||
public class SandboxModeTutorialFragment extends TutorialFragment {
|
||||
|
||||
@Override
|
||||
TutorialController createController(TutorialType type) {
|
||||
return new SandboxModeTutorialController(this, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
Class<? extends TutorialController> getControllerClass() {
|
||||
return SandboxModeTutorialController.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouch(View view, MotionEvent motionEvent) {
|
||||
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN && mTutorialController != null) {
|
||||
mTutorialController.setRippleHotspot(motionEvent.getX(), motionEvent.getY());
|
||||
}
|
||||
return super.onTouch(view, motionEvent);
|
||||
}
|
||||
}
|
|
@ -47,12 +47,11 @@ abstract class TutorialController implements BackGestureAttemptCallback,
|
|||
final TextView mTitleTextView;
|
||||
final TextView mSubtitleTextView;
|
||||
final TextView mFeedbackView;
|
||||
final View mLauncherView;
|
||||
final ClipIconView mFakeIconView;
|
||||
final View mFakeTaskView;
|
||||
final View mRippleView;
|
||||
final RippleDrawable mRippleDrawable;
|
||||
@Nullable final TutorialHandAnimation mHandCoachingAnimation;
|
||||
final TutorialHandAnimation mHandCoachingAnimation;
|
||||
final ImageView mHandCoachingView;
|
||||
final Button mActionTextButton;
|
||||
final Button mActionButton;
|
||||
|
@ -69,7 +68,6 @@ abstract class TutorialController implements BackGestureAttemptCallback,
|
|||
mTitleTextView = rootView.findViewById(R.id.gesture_tutorial_fragment_title_view);
|
||||
mSubtitleTextView = rootView.findViewById(R.id.gesture_tutorial_fragment_subtitle_view);
|
||||
mFeedbackView = rootView.findViewById(R.id.gesture_tutorial_fragment_feedback_view);
|
||||
mLauncherView = tutorialFragment.getLauncherView();
|
||||
mFakeIconView = rootView.findViewById(R.id.gesture_tutorial_fake_icon_view);
|
||||
mFakeTaskView = rootView.findViewById(R.id.gesture_tutorial_fake_task_view);
|
||||
mRippleView = rootView.findViewById(R.id.gesture_tutorial_ripple_view);
|
||||
|
@ -145,16 +143,13 @@ abstract class TutorialController implements BackGestureAttemptCallback,
|
|||
void onActionTextButtonClicked(View button) {}
|
||||
|
||||
void showHandCoachingAnimation() {
|
||||
if (isComplete() || mHandCoachingAnimation == null) {
|
||||
if (isComplete()) {
|
||||
return;
|
||||
}
|
||||
mHandCoachingAnimation.startLoopedAnimation(mTutorialType);
|
||||
}
|
||||
|
||||
void hideHandCoachingAnimation() {
|
||||
if (mHandCoachingAnimation == null) {
|
||||
return;
|
||||
}
|
||||
mHandCoachingAnimation.stop();
|
||||
mHandCoachingView.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
@ -167,10 +162,8 @@ abstract class TutorialController implements BackGestureAttemptCallback,
|
|||
|
||||
if (isComplete()) {
|
||||
hideHandCoachingAnimation();
|
||||
mLauncherView.setVisibility(View.INVISIBLE);
|
||||
} else {
|
||||
showHandCoachingAnimation();
|
||||
mLauncherView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -213,8 +206,7 @@ abstract class TutorialController implements BackGestureAttemptCallback,
|
|||
return mTutorialType == TutorialType.BACK_NAVIGATION_COMPLETE
|
||||
|| mTutorialType == TutorialType.HOME_NAVIGATION_COMPLETE
|
||||
|| mTutorialType == TutorialType.OVERVIEW_NAVIGATION_COMPLETE
|
||||
|| mTutorialType == TutorialType.ASSISTANT_COMPLETE
|
||||
|| mTutorialType == TutorialType.SANDBOX_MODE;
|
||||
|| mTutorialType == TutorialType.ASSISTANT_COMPLETE;
|
||||
}
|
||||
|
||||
/** Denotes the type of the tutorial. */
|
||||
|
@ -227,7 +219,6 @@ abstract class TutorialController implements BackGestureAttemptCallback,
|
|||
OVERVIEW_NAVIGATION,
|
||||
OVERVIEW_NAVIGATION_COMPLETE,
|
||||
ASSISTANT,
|
||||
ASSISTANT_COMPLETE,
|
||||
SANDBOX_MODE
|
||||
ASSISTANT_COMPLETE
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,6 @@ import androidx.annotation.Nullable;
|
|||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
|
||||
import com.android.launcher3.InvariantDeviceProfile;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.quickstep.interaction.TutorialController.TutorialType;
|
||||
|
||||
|
@ -43,10 +42,9 @@ abstract class TutorialFragment extends Fragment implements OnTouchListener {
|
|||
TutorialType mTutorialType;
|
||||
@Nullable TutorialController mTutorialController = null;
|
||||
View mRootView;
|
||||
@Nullable TutorialHandAnimation mHandCoachingAnimation = null;
|
||||
TutorialHandAnimation mHandCoachingAnimation;
|
||||
EdgeBackGestureHandler mEdgeBackGestureHandler;
|
||||
NavBarGestureHandler mNavBarGestureHandler;
|
||||
private View mLauncherView;
|
||||
|
||||
public static TutorialFragment newInstance(TutorialType tutorialType) {
|
||||
TutorialFragment fragment = getFragmentForTutorialType(tutorialType);
|
||||
|
@ -76,17 +74,13 @@ abstract class TutorialFragment extends Fragment implements OnTouchListener {
|
|||
case ASSISTANT:
|
||||
case ASSISTANT_COMPLETE:
|
||||
return new AssistantGestureTutorialFragment();
|
||||
case SANDBOX_MODE:
|
||||
return new SandboxModeTutorialFragment();
|
||||
default:
|
||||
Log.e(LOG_TAG, "Failed to find an appropriate fragment for " + tutorialType.name());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable Integer getHandAnimationResId() {
|
||||
return null;
|
||||
}
|
||||
abstract int getHandAnimationResId();
|
||||
|
||||
abstract TutorialController createController(TutorialType type);
|
||||
|
||||
|
@ -120,14 +114,8 @@ abstract class TutorialFragment extends Fragment implements OnTouchListener {
|
|||
return insets;
|
||||
});
|
||||
mRootView.setOnTouchListener(this);
|
||||
Integer handAnimationResId = getHandAnimationResId();
|
||||
if (handAnimationResId != null) {
|
||||
mHandCoachingAnimation =
|
||||
new TutorialHandAnimation(getContext(), mRootView, handAnimationResId);
|
||||
}
|
||||
InvariantDeviceProfile dp = InvariantDeviceProfile.INSTANCE.get(getContext());
|
||||
mLauncherView = new SandboxLauncherRenderer(getContext(), dp, true).getRenderedView();
|
||||
((ViewGroup) mRootView).addView(mLauncherView, 0);
|
||||
mHandCoachingAnimation = new TutorialHandAnimation(getContext(), mRootView,
|
||||
getHandAnimationResId());
|
||||
return mRootView;
|
||||
}
|
||||
|
||||
|
@ -140,25 +128,16 @@ abstract class TutorialFragment extends Fragment implements OnTouchListener {
|
|||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
|
||||
if (mHandCoachingAnimation != null) {
|
||||
mHandCoachingAnimation.stop();
|
||||
}
|
||||
mHandCoachingAnimation.stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouch(View view, MotionEvent motionEvent) {
|
||||
// Note: Using logical-or to ensure both functions get called.
|
||||
// Note: Using logical or to ensure both functions get called.
|
||||
return mEdgeBackGestureHandler.onTouch(view, motionEvent)
|
||||
| mNavBarGestureHandler.onTouch(view, motionEvent);
|
||||
}
|
||||
|
||||
boolean onInterceptTouch(MotionEvent motionEvent) {
|
||||
// Note: Using logical-or to ensure both functions get called.
|
||||
return mEdgeBackGestureHandler.onInterceptTouch(motionEvent)
|
||||
| mNavBarGestureHandler.onInterceptTouch(motionEvent);
|
||||
}
|
||||
|
||||
void onAttachedToWindow() {
|
||||
mEdgeBackGestureHandler.setViewGroupParent((ViewGroup) getRootView());
|
||||
}
|
||||
|
@ -189,11 +168,7 @@ abstract class TutorialFragment extends Fragment implements OnTouchListener {
|
|||
return mRootView;
|
||||
}
|
||||
|
||||
View getLauncherView() {
|
||||
return mLauncherView;
|
||||
}
|
||||
|
||||
@Nullable TutorialHandAnimation getHandAnimation() {
|
||||
TutorialHandAnimation getHandAnimation() {
|
||||
return mHandCoachingAnimation;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,68 +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 com.android.quickstep.util;
|
||||
|
||||
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
|
||||
|
||||
import androidx.annotation.UiThread;
|
||||
import androidx.annotation.WorkerThread;
|
||||
|
||||
/**
|
||||
* Utility class to executore a task on background and post the result on UI thread
|
||||
*/
|
||||
public abstract class CancellableTask<T> implements Runnable {
|
||||
|
||||
private boolean mCancelled = false;
|
||||
|
||||
@Override
|
||||
public final void run() {
|
||||
if (mCancelled) {
|
||||
return;
|
||||
}
|
||||
T result = getResultOnBg();
|
||||
if (mCancelled) {
|
||||
return;
|
||||
}
|
||||
MAIN_EXECUTOR.execute(() -> {
|
||||
if (mCancelled) {
|
||||
return;
|
||||
}
|
||||
handleResult(result);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Called on the worker thread to process the request. The return object is passed to
|
||||
* {@link #handleResult(Object)}
|
||||
*/
|
||||
@WorkerThread
|
||||
public abstract T getResultOnBg();
|
||||
|
||||
/**
|
||||
* Called on the UI thread to handle the final result.
|
||||
* @param result
|
||||
*/
|
||||
@UiThread
|
||||
public abstract void handleResult(T result);
|
||||
|
||||
/**
|
||||
* Cancels the request. If it is called before {@link #handleResult(Object)}, that method
|
||||
* will not be called
|
||||
*/
|
||||
public void cancel() {
|
||||
mCancelled = true;
|
||||
}
|
||||
}
|
|
@ -18,10 +18,8 @@ package com.android.quickstep.util;
|
|||
import static com.android.launcher3.LauncherState.NORMAL;
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||
import static com.android.launcher3.anim.Interpolators.DEACCEL;
|
||||
import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
|
||||
import static com.android.launcher3.anim.Interpolators.FINAL_FRAME;
|
||||
import static com.android.launcher3.anim.Interpolators.INSTANT;
|
||||
import static com.android.launcher3.anim.Interpolators.clampToProgress;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_COMPONENTS;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_ACTIONS_FADE;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE;
|
||||
|
@ -112,7 +110,7 @@ public class OverviewToHomeAnim {
|
|||
boolean isLayoutNaturalToLauncher = recentsView.getPagedOrientationHandler()
|
||||
.isLayoutNaturalToLauncher();
|
||||
config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, isLayoutNaturalToLauncher
|
||||
? clampToProgress(FAST_OUT_SLOW_IN, 0, 0.75f) : FINAL_FRAME);
|
||||
? DEACCEL : FINAL_FRAME);
|
||||
config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, FINAL_FRAME);
|
||||
config.setInterpolator(ANIM_OVERVIEW_SCALE, FINAL_FRAME);
|
||||
config.setInterpolator(ANIM_OVERVIEW_ACTIONS_FADE, INSTANT);
|
||||
|
|
|
@ -23,6 +23,7 @@ import static android.view.Surface.ROTATION_180;
|
|||
import static android.view.Surface.ROTATION_270;
|
||||
import static android.view.Surface.ROTATION_90;
|
||||
|
||||
import static com.android.launcher3.logging.LoggerUtils.extractObjectNameAndAddress;
|
||||
import static com.android.launcher3.states.RotationHelper.ALLOW_ROTATION_PREFERENCE_KEY;
|
||||
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
|
||||
import static com.android.quickstep.SysUINavigationMode.Mode.TWO_BUTTONS;
|
||||
|
@ -71,7 +72,6 @@ public final class RecentsOrientedState implements SharedPreferences.OnSharedPre
|
|||
|
||||
private static final String TAG = "RecentsOrientedState";
|
||||
private static final boolean DEBUG = false;
|
||||
private static final String DELIMITER_DOT = "\\.";
|
||||
|
||||
private ContentObserver mSystemAutoRotateObserver = new ContentObserver(new Handler()) {
|
||||
@Override
|
||||
|
@ -534,13 +534,4 @@ public final class RecentsOrientedState implements SharedPreferences.OnSharedPre
|
|||
? idp.landscapeProfile
|
||||
: idp.portraitProfile;
|
||||
}
|
||||
|
||||
/**
|
||||
* String conversion for only the helpful parts of {@link Object#toString()} method
|
||||
* @param stringToExtract "foo.bar.baz.MyObject@1234"
|
||||
* @return "MyObject@1234"
|
||||
*/
|
||||
private static String extractObjectNameAndAddress(String stringToExtract) {
|
||||
return stringToExtract.substring(stringToExtract.lastIndexOf(DELIMITER_DOT));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,8 +21,6 @@ import android.content.Context;
|
|||
import android.os.Handler;
|
||||
|
||||
import com.android.launcher3.LauncherAnimationRunner;
|
||||
import com.android.launcher3.LauncherAnimationRunner.AnimationResult;
|
||||
import com.android.launcher3.WrappedAnimationRunnerImpl;
|
||||
import com.android.launcher3.WrappedLauncherAnimationRunner;
|
||||
import com.android.systemui.shared.system.ActivityOptionsCompat;
|
||||
import com.android.systemui.shared.system.RemoteAnimationAdapterCompat;
|
||||
|
@ -30,17 +28,14 @@ import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
|
|||
|
||||
public abstract class RemoteAnimationProvider {
|
||||
|
||||
WrappedAnimationRunnerImpl mAnimationRunner;
|
||||
LauncherAnimationRunner mAnimationRunner;
|
||||
|
||||
public abstract AnimatorSet createWindowAnimation(RemoteAnimationTargetCompat[] appTargets,
|
||||
RemoteAnimationTargetCompat[] wallpaperTargets);
|
||||
|
||||
ActivityOptions toActivityOptions(Handler handler, long duration, Context context) {
|
||||
mAnimationRunner = new WrappedAnimationRunnerImpl() {
|
||||
@Override
|
||||
public Handler getHandler() {
|
||||
return handler;
|
||||
}
|
||||
mAnimationRunner = new LauncherAnimationRunner(handler,
|
||||
false /* startAtFrontOfQueue */) {
|
||||
|
||||
@Override
|
||||
public void onCreateAnimation(RemoteAnimationTargetCompat[] appTargets,
|
||||
|
@ -50,6 +45,7 @@ public abstract class RemoteAnimationProvider {
|
|||
};
|
||||
final LauncherAnimationRunner wrapper = new WrappedLauncherAnimationRunner(
|
||||
mAnimationRunner, false /* startAtFrontOfQueue */);
|
||||
|
||||
return ActivityOptionsCompat.makeRemoteAnimation(
|
||||
new RemoteAnimationAdapterCompat(wrapper, duration, 0));
|
||||
}
|
||||
|
|
|
@ -278,6 +278,7 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy {
|
|||
int start = mOrientationState.getOrientationHandler()
|
||||
.getPrimaryValue(mTaskRect.left, mTaskRect.top);
|
||||
mScrollState.screenCenter = start + mScrollState.scroll + mScrollState.halfPageSize;
|
||||
mScrollState.pageParentScale = recentsViewScale.value;
|
||||
mScrollState.updateInterpolation(start);
|
||||
mCurveScale = TaskView.getCurveScaleForInterpolation(mScrollState.linearInterpolation);
|
||||
}
|
||||
|
@ -296,9 +297,9 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy {
|
|||
mMatrix.postTranslate(insets.left, insets.top);
|
||||
mMatrix.postScale(scale, scale);
|
||||
|
||||
// Apply TaskView matrix: scale, translate, scroll
|
||||
mMatrix.postScale(mCurveScale, mCurveScale, taskWidth / 2, taskHeight / 2);
|
||||
// Apply TaskView matrix: translate, scale, scroll
|
||||
mMatrix.postTranslate(mTaskRect.left, mTaskRect.top + mOffsetY);
|
||||
mMatrix.postScale(mCurveScale, mCurveScale, taskWidth / 2, taskHeight / 2);
|
||||
mOrientationState.getOrientationHandler().set(
|
||||
mMatrix, MATRIX_POST_TRANSLATE, mScrollState.scroll);
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@ import androidx.annotation.StringRes;
|
|||
import com.android.launcher3.BaseActivity;
|
||||
import com.android.launcher3.BaseDraggingActivity;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||
import com.android.systemui.shared.recents.model.Task;
|
||||
|
||||
import java.time.Duration;
|
||||
|
@ -216,8 +217,8 @@ public final class DigitalWellBeingToast {
|
|||
view, 0, 0,
|
||||
view.getWidth(), view.getHeight());
|
||||
activity.startActivity(intent, options.toBundle());
|
||||
|
||||
// TODO: add WW logging on the app usage settings click.
|
||||
activity.getUserEventDispatcher().logActionOnControl(LauncherLogProto.Action.Touch.TAP,
|
||||
LauncherLogProto.ControlType.APP_USAGE_SETTINGS, view);
|
||||
} catch (ActivityNotFoundException e) {
|
||||
Log.e(TAG, "Failed to open app usage settings for task "
|
||||
+ mTask.getTopComponent().getPackageName(), e);
|
||||
|
|
|
@ -36,6 +36,7 @@ import android.view.Surface;
|
|||
import android.widget.FrameLayout;
|
||||
|
||||
import com.android.launcher3.BaseQuickstepLauncher;
|
||||
import com.android.launcher3.Hotseat;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.statehandlers.DepthController;
|
||||
import com.android.launcher3.statemanager.StateManager.StateListener;
|
||||
|
@ -176,8 +177,14 @@ public class LauncherRecentsView extends RecentsView<BaseQuickstepLauncher>
|
|||
|
||||
@Override
|
||||
protected boolean shouldStealTouchFromSiblingsBelow(MotionEvent ev) {
|
||||
return mActivity.getStateManager().getState().overviewUi
|
||||
&& super.shouldStealTouchFromSiblingsBelow(ev);
|
||||
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
|
||||
// Allow touches to go through to the hotseat.
|
||||
Hotseat hotseat = mActivity.getHotseat();
|
||||
boolean touchingHotseat = hotseat.isShown()
|
||||
&& mActivity.getDragLayer().isEventOverView(hotseat, ev, this);
|
||||
return !touchingHotseat;
|
||||
}
|
||||
return super.shouldStealTouchFromSiblingsBelow(ev);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -54,6 +54,7 @@ public class OverviewActionsView<T extends OverlayUICallbacks> extends FrameLayo
|
|||
HIDDEN_UNSUPPORTED_NAVIGATION,
|
||||
HIDDEN_NON_ZERO_ROTATION,
|
||||
HIDDEN_NO_TASKS,
|
||||
HIDDEN_GESTURE_RUNNING,
|
||||
HIDDEN_NO_RECENTS})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface ActionsHiddenFlags { }
|
||||
|
@ -61,7 +62,8 @@ public class OverviewActionsView<T extends OverlayUICallbacks> extends FrameLayo
|
|||
public static final int HIDDEN_UNSUPPORTED_NAVIGATION = 1 << 0;
|
||||
public static final int HIDDEN_NON_ZERO_ROTATION = 1 << 1;
|
||||
public static final int HIDDEN_NO_TASKS = 1 << 2;
|
||||
public static final int HIDDEN_NO_RECENTS = 1 << 3;
|
||||
public static final int HIDDEN_GESTURE_RUNNING = 1 << 3;
|
||||
public static final int HIDDEN_NO_RECENTS = 1 << 4;
|
||||
|
||||
@IntDef(flag = true, value = {
|
||||
DISABLED_SCROLLING,
|
||||
|
|
|
@ -35,14 +35,16 @@ import static com.android.launcher3.anim.Interpolators.ACCEL_2;
|
|||
import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_CLEAR_ALL;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_DISMISS_SWIPE_UP;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_SWIPE_DOWN;
|
||||
import static com.android.launcher3.statehandlers.DepthController.DEPTH;
|
||||
import static com.android.launcher3.uioverrides.touchcontrollers.TaskViewTouchController.SUCCESS_TRANSITION_PROGRESS;
|
||||
import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch.TAP;
|
||||
import static com.android.launcher3.userevent.nano.LauncherLogProto.ControlType.CLEAR_ALL_BUTTON;
|
||||
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
|
||||
import static com.android.launcher3.util.SystemUiController.UI_STATE_OVERVIEW;
|
||||
import static com.android.quickstep.TaskUtils.checkCurrentOrManagedUserId;
|
||||
import static com.android.quickstep.views.OverviewActionsView.HIDDEN_GESTURE_RUNNING;
|
||||
import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NON_ZERO_ROTATION;
|
||||
import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_RECENTS;
|
||||
import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_TASKS;
|
||||
|
@ -107,6 +109,7 @@ import com.android.launcher3.statehandlers.DepthController;
|
|||
import com.android.launcher3.statemanager.StatefulActivity;
|
||||
import com.android.launcher3.touch.PagedOrientationHandler;
|
||||
import com.android.launcher3.touch.PagedOrientationHandler.CurveProperties;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
|
||||
import com.android.launcher3.util.ComponentKey;
|
||||
import com.android.launcher3.util.DynamicResource;
|
||||
import com.android.launcher3.util.MultiValueAlpha;
|
||||
|
@ -115,7 +118,6 @@ import com.android.launcher3.util.ResourceBasedOverride.Overrides;
|
|||
import com.android.launcher3.util.Themes;
|
||||
import com.android.launcher3.util.ViewPool;
|
||||
import com.android.quickstep.BaseActivityInterface;
|
||||
import com.android.quickstep.GestureState;
|
||||
import com.android.quickstep.RecentsAnimationController;
|
||||
import com.android.quickstep.RecentsAnimationTargets;
|
||||
import com.android.quickstep.RecentsModel;
|
||||
|
@ -1127,6 +1129,7 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
|
|||
setEnableDrawingLiveTile(false);
|
||||
setRunningTaskHidden(true);
|
||||
setRunningTaskIconScaledDown(true);
|
||||
mActionsView.updateHiddenFlags(HIDDEN_GESTURE_RUNNING, true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1180,14 +1183,7 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
|
|||
}
|
||||
|
||||
/**
|
||||
* Called when a gesture from an app has finished, and an end target has been determined.
|
||||
*/
|
||||
public void onGestureEndTargetCalculated(GestureState.GestureEndTarget endTarget) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a gesture from an app has finished, and the animation to the target has ended.
|
||||
* Called when a gesture from an app has finished.
|
||||
*/
|
||||
public void onGestureAnimationEnd() {
|
||||
if (mOrientationState.setGestureActive(false)) {
|
||||
|
@ -1326,6 +1322,7 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
|
|||
}
|
||||
|
||||
private void animateActionsViewIn() {
|
||||
mActionsView.updateHiddenFlags(HIDDEN_GESTURE_RUNNING, false);
|
||||
ObjectAnimator anim = ObjectAnimator.ofFloat(
|
||||
mActionsView.getVisibilityAlpha(), MultiValueAlpha.VALUE, 0, 1);
|
||||
anim.setDuration(TaskView.SCALE_ICON_DURATION);
|
||||
|
@ -1410,12 +1407,13 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
|
|||
* Updates linearInterpolation for the provided child position
|
||||
*/
|
||||
public void updateInterpolation(float childStart) {
|
||||
float pageCenter = childStart + halfPageSize;
|
||||
float scaledHalfPageSize = halfPageSize / pageParentScale;
|
||||
float pageCenter = childStart + scaledHalfPageSize;
|
||||
float distanceFromScreenCenter = screenCenter - pageCenter;
|
||||
// How far the page has to move from the center to be offscreen, taking into account
|
||||
// the EDGE_SCALE_DOWN_FACTOR that will be applied at that position.
|
||||
float distanceToReachEdge = halfScreenSize
|
||||
+ halfPageSize * (1 - TaskView.EDGE_SCALE_DOWN_FACTOR);
|
||||
+ scaledHalfPageSize * (1 - TaskView.EDGE_SCALE_DOWN_FACTOR);
|
||||
linearInterpolation = Math.min(1,
|
||||
Math.abs(distanceFromScreenCenter) / distanceToReachEdge);
|
||||
}
|
||||
|
@ -1461,7 +1459,7 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
|
|||
public PendingAnimation createTaskDismissAnimation(TaskView taskView, boolean animateTaskView,
|
||||
boolean shouldRemoveTask, long duration) {
|
||||
if (mPendingAnimation != null) {
|
||||
mPendingAnimation.finish(false);
|
||||
mPendingAnimation.finish(false, Touch.SWIPE);
|
||||
}
|
||||
PendingAnimation anim = new PendingAnimation(duration);
|
||||
|
||||
|
@ -1623,7 +1621,7 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
|
|||
protected void runDismissAnimation(PendingAnimation pendingAnim) {
|
||||
AnimatorPlaybackController controller = pendingAnim.createPlaybackController();
|
||||
controller.dispatchOnStart();
|
||||
controller.setEndAction(() -> pendingAnim.finish(true));
|
||||
controller.setEndAction(() -> pendingAnim.finish(true, Touch.SWIPE));
|
||||
controller.getAnimationPlayer().setInterpolator(FAST_OUT_SLOW_IN);
|
||||
controller.start();
|
||||
}
|
||||
|
@ -1636,7 +1634,7 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
|
|||
@SuppressWarnings("unused")
|
||||
private void dismissAllTasks(View view) {
|
||||
runDismissAnimation(createAllTasksDismissAnimation(DISMISS_TASK_DURATION));
|
||||
mActivity.getStatsLogManager().logger().log(LAUNCHER_TASK_CLEAR_ALL);
|
||||
mActivity.getUserEventDispatcher().logActionOnControl(TAP, CLEAR_ALL_BUTTON);
|
||||
}
|
||||
|
||||
private void dismissCurrentTask() {
|
||||
|
@ -2161,12 +2159,7 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
|
|||
tv.notifyTaskLaunchFailed(TAG);
|
||||
}
|
||||
};
|
||||
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
|
||||
finishRecentsAnimation(false /* toRecents */, null);
|
||||
onLaunchResult.accept(true /* success */);
|
||||
} else {
|
||||
tv.launchTask(false, onLaunchResult, getHandler());
|
||||
}
|
||||
tv.launchTask(false, onLaunchResult, getHandler());
|
||||
Task task = tv.getTask();
|
||||
if (task != null) {
|
||||
mActivity.getStatsLogManager().logger().withItemInfo(tv.getItemInfo())
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
package com.android.quickstep.views;
|
||||
|
||||
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
|
||||
import static com.android.quickstep.views.TaskThumbnailView.DIM_ALPHA;
|
||||
|
||||
import android.animation.Animator;
|
||||
|
@ -230,16 +229,7 @@ public class TaskMenuView extends AbstractFloatingView {
|
|||
menuOptionView.findViewById(R.id.icon), menuOptionView.findViewById(R.id.text));
|
||||
LayoutParams lp = (LayoutParams) menuOptionView.getLayoutParams();
|
||||
mTaskView.getPagedOrientationHandler().setLayoutParamsForTaskMenuOptionItem(lp);
|
||||
menuOptionView.setOnClickListener(view -> {
|
||||
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
|
||||
RecentsView recentsView = mTaskView.getRecentsView();
|
||||
recentsView.switchToScreenshot(null,
|
||||
() -> recentsView.finishRecentsAnimation(true /* toRecents */,
|
||||
() -> menuOption.onClick(view)));
|
||||
} else {
|
||||
menuOption.onClick(view);
|
||||
}
|
||||
});
|
||||
menuOptionView.setOnClickListener(menuOption);
|
||||
mOptionLayout.addView(menuOptionView);
|
||||
}
|
||||
|
||||
|
|
|
@ -73,11 +73,15 @@ import com.android.launcher3.Utilities;
|
|||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||
import com.android.launcher3.anim.Interpolators;
|
||||
import com.android.launcher3.anim.PendingAnimation;
|
||||
import com.android.launcher3.logging.UserEventDispatcher;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.popup.SystemShortcut;
|
||||
import com.android.launcher3.testing.TestLogging;
|
||||
import com.android.launcher3.testing.TestProtocol;
|
||||
import com.android.launcher3.touch.PagedOrientationHandler;
|
||||
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.launcher3.util.ComponentKey;
|
||||
import com.android.launcher3.util.TransformingTouchDelegate;
|
||||
import com.android.launcher3.util.ViewPool.Reusable;
|
||||
|
@ -86,7 +90,6 @@ import com.android.quickstep.TaskIconCache;
|
|||
import com.android.quickstep.TaskOverlayFactory;
|
||||
import com.android.quickstep.TaskThumbnailCache;
|
||||
import com.android.quickstep.TaskUtils;
|
||||
import com.android.quickstep.util.CancellableTask;
|
||||
import com.android.quickstep.util.RecentsOrientedState;
|
||||
import com.android.quickstep.util.TaskCornerRadius;
|
||||
import com.android.quickstep.views.RecentsView.PageCallbacks;
|
||||
|
@ -186,8 +189,8 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
|
|||
private boolean mShowScreenshot;
|
||||
|
||||
// The current background requests to load the task thumbnail and icon
|
||||
private CancellableTask mThumbnailLoadRequest;
|
||||
private CancellableTask mIconLoadRequest;
|
||||
private TaskThumbnailCache.ThumbnailLoadRequest mThumbnailLoadRequest;
|
||||
private TaskIconCache.IconLoadRequest mIconLoadRequest;
|
||||
|
||||
// Order in which the footers appear. Lower order appear below higher order.
|
||||
public static final int INDEX_DIGITAL_WELLBEING_TOAST = 0;
|
||||
|
@ -217,7 +220,6 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
|
|||
}
|
||||
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
|
||||
if (isRunningTask()) {
|
||||
// TODO: Replace this animation with createRecentsWindowAnimator
|
||||
createLaunchAnimationForRunningTask().start();
|
||||
} else {
|
||||
launchTask(true /* animate */);
|
||||
|
@ -363,7 +365,10 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
|
|||
final PendingAnimation pendingAnimation = getRecentsView().createTaskLaunchAnimation(
|
||||
this, RECENTS_LAUNCH_DURATION, TOUCH_RESPONSE_INTERPOLATOR);
|
||||
AnimatorPlaybackController currentAnimation = pendingAnimation.createPlaybackController();
|
||||
currentAnimation.setEndAction(() -> pendingAnimation.finish(true));
|
||||
currentAnimation.setEndAction(() -> {
|
||||
pendingAnimation.finish(true, Touch.SWIPE);
|
||||
launchTask(false);
|
||||
});
|
||||
return currentAnimation;
|
||||
}
|
||||
|
||||
|
@ -386,6 +391,20 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
|
|||
|
||||
public void launchTask(boolean animate, boolean freezeTaskList, Consumer<Boolean> resultCallback,
|
||||
Handler resultCallbackHandler) {
|
||||
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
|
||||
if (isRunningTask()) {
|
||||
getRecentsView().finishRecentsAnimation(false /* toRecents */,
|
||||
() -> resultCallbackHandler.post(() -> resultCallback.accept(true)));
|
||||
} else {
|
||||
launchTaskInternal(animate, freezeTaskList, resultCallback, resultCallbackHandler);
|
||||
}
|
||||
} else {
|
||||
launchTaskInternal(animate, freezeTaskList, resultCallback, resultCallbackHandler);
|
||||
}
|
||||
}
|
||||
|
||||
private void launchTaskInternal(boolean animate, boolean freezeTaskList,
|
||||
Consumer<Boolean> resultCallback, Handler resultCallbackHandler) {
|
||||
if (mTask != null) {
|
||||
final ActivityOptions opts;
|
||||
TestLogging.recordEvent(
|
||||
|
@ -462,13 +481,15 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
|
|||
}
|
||||
}
|
||||
|
||||
private boolean showTaskMenu() {
|
||||
private boolean showTaskMenu(int action) {
|
||||
if (!getRecentsView().isClearAllHidden()) {
|
||||
getRecentsView().snapToPage(getRecentsView().indexOfChild(this));
|
||||
} else {
|
||||
mMenuView = TaskMenuView.showForTask(this);
|
||||
mActivity.getStatsLogManager().logger().withItemInfo(getItemInfo())
|
||||
.log(LAUNCHER_TASK_ICON_TAP_OR_LONGPRESS);
|
||||
UserEventDispatcher.newInstance(getContext()).logActionOnItem(action, Direction.NONE,
|
||||
LauncherLogProto.ItemType.TASK_ICON);
|
||||
if (mMenuView != null) {
|
||||
mMenuView.addOnAttachStateChangeListener(mTaskMenuStateListener);
|
||||
}
|
||||
|
@ -479,10 +500,10 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
|
|||
private void setIcon(Drawable icon) {
|
||||
if (icon != null) {
|
||||
mIconView.setDrawable(icon);
|
||||
mIconView.setOnClickListener(v -> showTaskMenu());
|
||||
mIconView.setOnClickListener(v -> showTaskMenu(Touch.TAP));
|
||||
mIconView.setOnLongClickListener(v -> {
|
||||
requestDisallowInterceptTouchEvent(true);
|
||||
return showTaskMenu();
|
||||
return showTaskMenu(Touch.LONGPRESS);
|
||||
});
|
||||
} else {
|
||||
mIconView.setDrawable(null);
|
||||
|
|
|
@ -3,8 +3,6 @@ package com.android.quickstep;
|
|||
import static androidx.test.InstrumentationRegistry.getInstrumentation;
|
||||
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||
import static com.android.launcher3.util.rule.TestStabilityRule.PLATFORM_POSTSUBMIT;
|
||||
import static com.android.launcher3.util.rule.TestStabilityRule.UNBUNDLED_POSTSUBMIT;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
|
@ -13,12 +11,12 @@ import static org.junit.Assert.assertTrue;
|
|||
import android.app.PendingIntent;
|
||||
import android.app.usage.UsageStatsManager;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
|
||||
import androidx.test.filters.LargeTest;
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.util.rule.TestStabilityRule;
|
||||
import com.android.quickstep.views.DigitalWellBeingToast;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.quickstep.views.TaskView;
|
||||
|
@ -36,6 +34,9 @@ public class DigitalWellBeingToastTest extends AbstractQuickStepTest {
|
|||
|
||||
@Test
|
||||
public void testToast() throws Exception {
|
||||
// b/150303529
|
||||
if (Build.MODEL.contains("Cuttlefish")) return;
|
||||
|
||||
startAppFast(CALCULATOR_PACKAGE);
|
||||
|
||||
final UsageStatsManager usageStatsManager =
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?><!-- 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.
|
||||
-->
|
||||
<com.android.launcher3.views.SearchResultIconRow xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:launcher="http://schemas.android.com/apk/res-auto"
|
||||
style="@style/BaseIcon"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:drawablePadding="@dimen/dynamic_grid_icon_drawable_padding"
|
||||
android:gravity="start|center_vertical"
|
||||
android:textAlignment="viewStart"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="16sp"
|
||||
android:padding="@dimen/dynamic_grid_edge_margin"
|
||||
launcher:iconDisplay="hero_app"
|
||||
launcher:layoutHorizontal="true"
|
||||
>
|
||||
|
||||
</com.android.launcher3.views.SearchResultIconRow>
|
|
@ -0,0 +1,42 @@
|
|||
<?xml version="1.0" encoding="utf-8"?><!-- 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.
|
||||
-->
|
||||
<com.android.launcher3.views.SearchResultShortcut xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:launcher="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:padding="@dimen/dynamic_grid_edge_margin">
|
||||
|
||||
<com.android.launcher3.BubbleTextView
|
||||
android:id="@+id/bubble_text"
|
||||
style="@style/BaseIcon"
|
||||
android:drawablePadding="@dimen/dynamic_grid_icon_drawable_padding"
|
||||
android:gravity="start|center_vertical"
|
||||
android:textAlignment="viewStart"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="16sp"
|
||||
android:layout_height="wrap_content"
|
||||
launcher:iconDisplay="hero_app"
|
||||
launcher:layoutHorizontal="true" />
|
||||
|
||||
<View
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="@dimen/deep_shortcut_icon_size"
|
||||
android:layout_height="@dimen/deep_shortcut_icon_size"
|
||||
android:layout_gravity="start|center_vertical"
|
||||
android:background="@drawable/ic_deepshortcut_placeholder" />
|
||||
|
||||
</com.android.launcher3.views.SearchResultShortcut>
|
|
@ -1,38 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?><!-- 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.
|
||||
-->
|
||||
<com.android.launcher3.views.SearchResultSuggestRow xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
style="@style/TextHeadline"
|
||||
android:id="@+id/section_title"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center_vertical"
|
||||
android:padding="4dp"
|
||||
android:minHeight="48dp"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="14sp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
style="@style/TextTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="8dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="14sp" />
|
||||
|
||||
</com.android.launcher3.views.SearchResultSuggestRow>
|
|
@ -1,19 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- 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.
|
||||
-->
|
||||
<com.android.launcher3.views.ThumbnailSearchResultView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="125dp"
|
||||
android:layout_height="125dp"/>
|
|
@ -59,6 +59,7 @@
|
|||
<bool name="hotseat_transpose_layout_with_orientation">true</bool>
|
||||
|
||||
<!-- Various classes overriden by projects/build flavors. -->
|
||||
<string name="user_event_dispatcher_class" translatable="false"></string>
|
||||
<string name="folder_name_provider_class" translatable="false"></string>
|
||||
<string name="stats_log_manager_class" translatable="false"></string>
|
||||
<string name="app_transition_manager_class" translatable="false"></string>
|
||||
|
|
|
@ -21,6 +21,7 @@ import static com.android.launcher3.util.Preconditions.assertNotNull;
|
|||
|
||||
import static org.junit.Assert.assertNotSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.UserManager;
|
||||
|
@ -29,6 +30,8 @@ import android.provider.Settings;
|
|||
import com.android.launcher3.InvariantDeviceProfile;
|
||||
import com.android.launcher3.allapps.AllAppsPagedView;
|
||||
import com.android.launcher3.allapps.AllAppsRecyclerView;
|
||||
import com.android.launcher3.logging.UserEventDispatcher;
|
||||
import com.android.launcher3.shadows.ShadowOverrides;
|
||||
import com.android.launcher3.util.LauncherLayoutBuilder;
|
||||
import com.android.launcher3.util.LauncherModelHelper;
|
||||
|
||||
|
@ -66,6 +69,8 @@ public class SDWorkModeTest {
|
|||
mModelHelper = new LauncherModelHelper();
|
||||
mTargetContext = RuntimeEnvironment.application;
|
||||
mIdp = InvariantDeviceProfile.INSTANCE.get(mTargetContext);
|
||||
ShadowOverrides.setProvider(UserEventDispatcher.class,
|
||||
c -> mock(UserEventDispatcher.class));
|
||||
Settings.Global.putFloat(mTargetContext.getContentResolver(),
|
||||
Settings.Global.WINDOW_ANIMATION_SCALE, 0);
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ import static com.android.launcher3.util.LauncherUIHelper.doLayout;
|
|||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.SystemClock;
|
||||
|
@ -35,6 +36,8 @@ import com.android.launcher3.LauncherState;
|
|||
import com.android.launcher3.folder.Folder;
|
||||
import com.android.launcher3.folder.FolderIcon;
|
||||
import com.android.launcher3.folder.FolderPagedView;
|
||||
import com.android.launcher3.logging.UserEventDispatcher;
|
||||
import com.android.launcher3.shadows.ShadowOverrides;
|
||||
import com.android.launcher3.util.LauncherLayoutBuilder;
|
||||
import com.android.launcher3.util.LauncherLayoutBuilder.FolderBuilder;
|
||||
import com.android.launcher3.util.LauncherModelHelper;
|
||||
|
@ -67,6 +70,8 @@ public class LauncherUIScrollTest {
|
|||
mModelHelper = new LauncherModelHelper();
|
||||
mTargetContext = RuntimeEnvironment.application;
|
||||
mIdp = InvariantDeviceProfile.INSTANCE.get(mTargetContext);
|
||||
ShadowOverrides.setProvider(UserEventDispatcher.class,
|
||||
c -> mock(UserEventDispatcher.class));
|
||||
|
||||
Settings.Global.putFloat(mTargetContext.getContentResolver(),
|
||||
Settings.Global.WINDOW_ANIMATION_SCALE, 0);
|
||||
|
|
|
@ -37,6 +37,8 @@ import androidx.annotation.IntDef;
|
|||
|
||||
import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
|
||||
import com.android.launcher3.logging.StatsLogManager;
|
||||
import com.android.launcher3.logging.UserEventDispatcher;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||
import com.android.launcher3.util.SystemUiController;
|
||||
import com.android.launcher3.util.ViewCache;
|
||||
import com.android.launcher3.views.ActivityContext;
|
||||
|
@ -80,6 +82,7 @@ public abstract class BaseActivity extends Activity implements ActivityContext {
|
|||
new ArrayList<>();
|
||||
|
||||
protected DeviceProfile mDeviceProfile;
|
||||
protected UserEventDispatcher mUserEventDispatcher;
|
||||
protected StatsLogManager mStatsLogManager;
|
||||
protected SystemUiController mSystemUiController;
|
||||
|
||||
|
@ -141,6 +144,8 @@ public abstract class BaseActivity extends Activity implements ActivityContext {
|
|||
return mDeviceProfile;
|
||||
}
|
||||
|
||||
public void modifyUserEvent(LauncherLogProto.LauncherEvent event) {}
|
||||
|
||||
public final StatsLogManager getStatsLogManager() {
|
||||
if (mStatsLogManager == null) {
|
||||
mStatsLogManager = StatsLogManager.newInstance(this);
|
||||
|
@ -148,6 +153,13 @@ public abstract class BaseActivity extends Activity implements ActivityContext {
|
|||
return mStatsLogManager;
|
||||
}
|
||||
|
||||
public final UserEventDispatcher getUserEventDispatcher() {
|
||||
if (mUserEventDispatcher == null) {
|
||||
mUserEventDispatcher = UserEventDispatcher.newInstance(this);
|
||||
}
|
||||
return mUserEventDispatcher;
|
||||
}
|
||||
|
||||
public SystemUiController getSystemUiController() {
|
||||
if (mSystemUiController == null) {
|
||||
mSystemUiController = new SystemUiController(getWindow());
|
||||
|
|
|
@ -23,7 +23,6 @@ import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound;
|
|||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.content.res.TypedArray;
|
||||
|
@ -31,8 +30,6 @@ import android.graphics.Canvas;
|
|||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.PorterDuff.Mode;
|
||||
import android.graphics.PorterDuffColorFilter;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
@ -46,8 +43,6 @@ import android.view.View;
|
|||
import android.view.ViewDebug;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.core.graphics.ColorUtils;
|
||||
|
||||
import com.android.launcher3.Launcher.OnResumeCallback;
|
||||
import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
|
||||
import com.android.launcher3.dot.DotInfo;
|
||||
|
@ -55,7 +50,6 @@ import com.android.launcher3.dragndrop.DraggableView;
|
|||
import com.android.launcher3.folder.FolderIcon;
|
||||
import com.android.launcher3.graphics.IconPalette;
|
||||
import com.android.launcher3.graphics.IconShape;
|
||||
import com.android.launcher3.graphics.PlaceHolderIconDrawable;
|
||||
import com.android.launcher3.graphics.PreloadIconDrawable;
|
||||
import com.android.launcher3.icons.DotRenderer;
|
||||
import com.android.launcher3.icons.IconCache.IconLoadRequest;
|
||||
|
@ -65,7 +59,6 @@ import com.android.launcher3.model.data.ItemInfo;
|
|||
import com.android.launcher3.model.data.ItemInfoWithIcon;
|
||||
import com.android.launcher3.model.data.PackageItemInfo;
|
||||
import com.android.launcher3.model.data.PromiseAppInfo;
|
||||
import com.android.launcher3.model.data.RemoteActionItemInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.util.SafeCloseable;
|
||||
import com.android.launcher3.views.ActivityContext;
|
||||
|
@ -91,8 +84,6 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
|||
private final PointF mTranslationForReorderBounce = new PointF(0, 0);
|
||||
private final PointF mTranslationForReorderPreview = new PointF(0, 0);
|
||||
|
||||
private static final int ICON_UPDATE_ANIMATION_DURATION = 375;
|
||||
|
||||
private float mScaleForReorderBounce = 1f;
|
||||
|
||||
private static final Property<BubbleTextView, Float> DOT_SCALE_PROPERTY
|
||||
|
@ -301,14 +292,6 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
|||
verifyHighRes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply label and tag using a {@link RemoteActionItemInfo}
|
||||
*/
|
||||
public void applyFromRemoteActionInfo(RemoteActionItemInfo remoteActionItemInfo) {
|
||||
applyIconAndLabel(remoteActionItemInfo);
|
||||
setTag(remoteActionItemInfo);
|
||||
}
|
||||
|
||||
private void applyIconAndLabel(ItemInfoWithIcon info) {
|
||||
FastBitmapDrawable iconDrawable = newIcon(getContext(), info);
|
||||
mDotParams.color = IconPalette.getMutedColor(info.bitmap.color, 0.54f);
|
||||
|
@ -653,14 +636,11 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
|||
mDisableRelayout = mIcon != null;
|
||||
|
||||
icon.setBounds(0, 0, mIconSize, mIconSize);
|
||||
|
||||
updateIcon(icon);
|
||||
|
||||
// If the current icon is a placeholder color, animate its update.
|
||||
if (mIcon != null && mIcon instanceof PlaceHolderIconDrawable) {
|
||||
animateIconUpdate((PlaceHolderIconDrawable) mIcon, icon);
|
||||
if (mLayoutHorizontal) {
|
||||
setCompoundDrawablesRelative(icon, null, null, null);
|
||||
} else {
|
||||
setCompoundDrawables(null, icon, null, null);
|
||||
}
|
||||
|
||||
mDisableRelayout = false;
|
||||
}
|
||||
|
||||
|
@ -690,8 +670,6 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
|||
mActivity.invalidateParent(info);
|
||||
} else if (info instanceof PackageItemInfo) {
|
||||
applyFromItemInfoWithIcon((PackageItemInfo) info);
|
||||
} else if (info instanceof RemoteActionItemInfo) {
|
||||
applyFromRemoteActionInfo((RemoteActionItemInfo) info);
|
||||
}
|
||||
|
||||
mDisableRelayout = false;
|
||||
|
@ -798,33 +776,4 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
|||
((FastBitmapDrawable) mIcon).setScale(1f);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateIcon(Drawable newIcon) {
|
||||
if (mLayoutHorizontal) {
|
||||
setCompoundDrawablesRelative(newIcon, null, null, null);
|
||||
} else {
|
||||
setCompoundDrawables(null, newIcon, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
private static void animateIconUpdate(PlaceHolderIconDrawable oldIcon, Drawable newIcon) {
|
||||
int placeholderColor = oldIcon.mPaint.getColor();
|
||||
int originalAlpha = Color.alpha(placeholderColor);
|
||||
|
||||
ValueAnimator iconUpdateAnimation = ValueAnimator.ofInt(originalAlpha, 0);
|
||||
iconUpdateAnimation.setDuration(ICON_UPDATE_ANIMATION_DURATION);
|
||||
iconUpdateAnimation.addUpdateListener(valueAnimator -> {
|
||||
int newAlpha = (int) valueAnimator.getAnimatedValue();
|
||||
int newColor = ColorUtils.setAlphaComponent(placeholderColor, newAlpha);
|
||||
|
||||
newIcon.setColorFilter(new PorterDuffColorFilter(newColor, Mode.SRC_ATOP));
|
||||
});
|
||||
iconUpdateAnimation.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
newIcon.setColorFilter(null);
|
||||
}
|
||||
});
|
||||
iconUpdateAnimation.start();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ import com.android.launcher3.dragndrop.DragLayer;
|
|||
import com.android.launcher3.dragndrop.DragOptions;
|
||||
import com.android.launcher3.dragndrop.DragView;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
|
||||
import com.android.launcher3.util.Themes;
|
||||
import com.android.launcher3.util.Thunk;
|
||||
|
||||
|
@ -394,4 +395,6 @@ public abstract class ButtonDropTarget extends TextView
|
|||
TextUtils.TruncateAt.END);
|
||||
return !mText.equals(displayedText);
|
||||
}
|
||||
|
||||
public abstract Target getDropTargetForLogging();
|
||||
}
|
||||
|
|
|
@ -323,8 +323,11 @@ public class CellLayout extends ViewGroup {
|
|||
|
||||
@Override
|
||||
public boolean onInterceptTouchEvent(MotionEvent ev) {
|
||||
return mTouchHelper != null
|
||||
|| (mInterceptTouchListener != null && mInterceptTouchListener.onTouch(this, ev));
|
||||
if (mTouchHelper != null
|
||||
|| (mInterceptTouchListener != null && mInterceptTouchListener.onTouch(this, ev))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void enableHardwareLayer(boolean hasLayer) {
|
||||
|
|
|
@ -18,7 +18,8 @@ package com.android.launcher3;
|
|||
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ITEM_DROPPED_ON_CANCEL;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ITEM_DROPPED_ON_REMOVE;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_UNDO;
|
||||
import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch.TAP;
|
||||
import static com.android.launcher3.userevent.nano.LauncherLogProto.ControlType.UNDO;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
|
@ -27,19 +28,22 @@ import android.view.View;
|
|||
|
||||
import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
|
||||
import com.android.launcher3.dragndrop.DragOptions;
|
||||
import com.android.launcher3.logging.LoggerUtils;
|
||||
import com.android.launcher3.logging.StatsLogManager;
|
||||
import com.android.launcher3.model.ModelWriter;
|
||||
import com.android.launcher3.model.data.FolderInfo;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ControlType;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
|
||||
import com.android.launcher3.views.Snackbar;
|
||||
|
||||
public class DeleteDropTarget extends ButtonDropTarget {
|
||||
|
||||
private final StatsLogManager mStatsLogManager;
|
||||
|
||||
private StatsLogManager.LauncherEvent mLauncherEvent;
|
||||
private int mControlType = ControlType.DEFAULT_CONTROLTYPE;
|
||||
|
||||
public DeleteDropTarget(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
|
@ -111,8 +115,8 @@ public class DeleteDropTarget extends ButtonDropTarget {
|
|||
* Set mControlType depending on the drag item.
|
||||
*/
|
||||
private void setControlTypeBasedOnDragSource(ItemInfo item) {
|
||||
mLauncherEvent = item.id != ItemInfo.NO_ID ? LAUNCHER_ITEM_DROPPED_ON_REMOVE
|
||||
: LAUNCHER_ITEM_DROPPED_ON_CANCEL;
|
||||
mControlType = item.id != ItemInfo.NO_ID ? ControlType.REMOVE_TARGET
|
||||
: ControlType.CANCEL_TARGET;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -123,7 +127,8 @@ public class DeleteDropTarget extends ButtonDropTarget {
|
|||
}
|
||||
super.onDrop(d, options);
|
||||
mStatsLogManager.logger().withInstanceId(d.logInstanceId)
|
||||
.log(mLauncherEvent);
|
||||
.log(mControlType == ControlType.REMOVE_TARGET ? LAUNCHER_ITEM_DROPPED_ON_REMOVE
|
||||
: LAUNCHER_ITEM_DROPPED_ON_CANCEL);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -136,7 +141,7 @@ public class DeleteDropTarget extends ButtonDropTarget {
|
|||
Runnable onUndoClicked = () -> {
|
||||
mLauncher.setPageToBindSynchronously(itemPage);
|
||||
modelWriter.abortDelete();
|
||||
mLauncher.getStatsLogManager().logger().log(LAUNCHER_UNDO);
|
||||
mLauncher.getUserEventDispatcher().logActionOnControl(TAP, UNDO);
|
||||
};
|
||||
Snackbar.show(mLauncher, R.string.item_removed, R.string.undo,
|
||||
modelWriter::commitDelete, onUndoClicked);
|
||||
|
@ -156,4 +161,11 @@ public class DeleteDropTarget extends ButtonDropTarget {
|
|||
mLauncher.getDragLayer()
|
||||
.announceForAccessibility(getContext().getString(R.string.item_removed));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Target getDropTargetForLogging() {
|
||||
Target t = LoggerUtils.newTarget(Target.Type.CONTROL);
|
||||
t.controlType = mControlType;
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,8 +33,6 @@ import android.graphics.Rect;
|
|||
import android.graphics.drawable.Drawable;
|
||||
import android.util.Property;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.graphics.PlaceHolderIconDrawable;
|
||||
import com.android.launcher3.icons.BitmapInfo;
|
||||
import com.android.launcher3.model.data.ItemInfoWithIcon;
|
||||
|
@ -56,8 +54,6 @@ public class FastBitmapDrawable extends Drawable {
|
|||
protected Bitmap mBitmap;
|
||||
protected final int mIconColor;
|
||||
|
||||
@Nullable private ColorFilter mColorFilter;
|
||||
|
||||
private boolean mIsPressed;
|
||||
private boolean mIsDisabled;
|
||||
private float mDisabledAlpha = 1f;
|
||||
|
@ -119,8 +115,7 @@ public class FastBitmapDrawable extends Drawable {
|
|||
|
||||
@Override
|
||||
public void setColorFilter(ColorFilter cf) {
|
||||
mColorFilter = cf;
|
||||
updateFilter();
|
||||
// No op
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -270,7 +265,7 @@ public class FastBitmapDrawable extends Drawable {
|
|||
* Updates the paint to reflect the current brightness and saturation.
|
||||
*/
|
||||
protected void updateFilter() {
|
||||
mPaint.setColorFilter(mIsDisabled ? getDisabledColorFilter() : mColorFilter);
|
||||
mPaint.setColorFilter(mIsDisabled ? getDisabledColorFilter() : null);
|
||||
invalidateSelf();
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
|
||||
package com.android.launcher3;
|
||||
|
||||
import static com.android.launcher3.logging.LoggerUtils.newContainerTarget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.util.AttributeSet;
|
||||
|
@ -25,10 +27,14 @@ import android.view.ViewDebug;
|
|||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
/**
|
||||
* View class that represents the bottom row of the home screen.
|
||||
*/
|
||||
public class Hotseat extends CellLayout implements Insettable {
|
||||
import com.android.launcher3.logging.StatsLogUtils.LogContainerProvider;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class Hotseat extends CellLayout implements LogContainerProvider, Insettable {
|
||||
|
||||
@ViewDebug.ExportedProperty(category = "launcher")
|
||||
private boolean mHasVerticalHotseat;
|
||||
|
@ -72,6 +78,15 @@ public class Hotseat extends CellLayout implements Insettable {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillInLogContainerData(ItemInfo childInfo, Target child,
|
||||
ArrayList<Target> parents) {
|
||||
child.rank = childInfo.rank;
|
||||
child.gridX = childInfo.cellX;
|
||||
child.gridY = childInfo.cellY;
|
||||
parents.add(newContainerTarget(LauncherLogProto.ContainerType.HOTSEAT));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInsets(Rect insets) {
|
||||
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
|
||||
|
|
|
@ -18,7 +18,6 @@ package com.android.launcher3;
|
|||
|
||||
import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
|
||||
import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE;
|
||||
import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_NO;
|
||||
import static android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
|
||||
|
||||
import static com.android.launcher3.AbstractFloatingView.TYPE_ALL;
|
||||
|
@ -37,10 +36,11 @@ import static com.android.launcher3.LauncherState.OVERVIEW;
|
|||
import static com.android.launcher3.LauncherState.SPRING_LOADED;
|
||||
import static com.android.launcher3.Utilities.postAsyncCallback;
|
||||
import static com.android.launcher3.dragndrop.DragLayer.ALPHA_INDEX_LAUNCHER_LOAD;
|
||||
import static com.android.launcher3.logging.LoggerUtils.newContainerTarget;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_BACKGROUND;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_HOME;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ONRESUME;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ONSTOP;
|
||||
import static com.android.launcher3.logging.StatsLogManager.containerTypeToAtomState;
|
||||
import static com.android.launcher3.model.ItemInstallQueue.FLAG_ACTIVITY_PAUSED;
|
||||
import static com.android.launcher3.model.ItemInstallQueue.FLAG_DRAG_AND_DROP;
|
||||
import static com.android.launcher3.model.ItemInstallQueue.FLAG_LOADER_RUNNING;
|
||||
|
@ -70,7 +70,6 @@ import android.content.SharedPreferences;
|
|||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Configuration;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.CancellationSignal;
|
||||
|
@ -89,10 +88,9 @@ import android.view.Menu;
|
|||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowManager.LayoutParams;
|
||||
import android.view.WindowManager;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.view.animation.OvershootInterpolator;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.CallSuper;
|
||||
|
@ -119,13 +117,13 @@ import com.android.launcher3.dragndrop.DragLayer;
|
|||
import com.android.launcher3.dragndrop.DragView;
|
||||
import com.android.launcher3.folder.FolderGridOrganizer;
|
||||
import com.android.launcher3.folder.FolderIcon;
|
||||
import com.android.launcher3.icons.BitmapRenderer;
|
||||
import com.android.launcher3.icons.IconCache;
|
||||
import com.android.launcher3.keyboard.CustomActionsPopup;
|
||||
import com.android.launcher3.keyboard.ViewGroupFocusHelper;
|
||||
import com.android.launcher3.logger.LauncherAtom;
|
||||
import com.android.launcher3.logging.FileLog;
|
||||
import com.android.launcher3.logging.StatsLogManager;
|
||||
import com.android.launcher3.logging.UserEventDispatcher;
|
||||
import com.android.launcher3.model.BgDataModel.Callbacks;
|
||||
import com.android.launcher3.model.ItemInstallQueue;
|
||||
import com.android.launcher3.model.ModelUtils;
|
||||
|
@ -153,6 +151,9 @@ import com.android.launcher3.testing.TestProtocol;
|
|||
import com.android.launcher3.touch.AllAppsSwipeController;
|
||||
import com.android.launcher3.touch.ItemClickHandler;
|
||||
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
|
||||
import com.android.launcher3.util.ActivityResultInfo;
|
||||
import com.android.launcher3.util.ActivityTracker;
|
||||
import com.android.launcher3.util.ComponentKey;
|
||||
|
@ -268,8 +269,6 @@ public class Launcher extends StatefulActivity<LauncherState> implements Launche
|
|||
private static final int APPS_VIEW_ALPHA_CHANNEL_INDEX = 1;
|
||||
private static final int SCRIM_VIEW_ALPHA_CHANNEL_INDEX = 0;
|
||||
|
||||
private static final int THEME_CROSS_FADE_ANIMATION_DURATION = 375;
|
||||
|
||||
private LauncherAppTransitionManager mAppTransitionManager;
|
||||
private Configuration mOldConfig;
|
||||
|
||||
|
@ -401,7 +400,6 @@ public class Launcher extends StatefulActivity<LauncherState> implements Launche
|
|||
|
||||
inflateRootView(R.layout.launcher);
|
||||
setupViews();
|
||||
crossFadeWithPreviousAppearance();
|
||||
mPopupDataProvider = new PopupDataProvider(this::updateNotificationDots);
|
||||
|
||||
mAppTransitionManager = LauncherAppTransitionManager.newInstance(this);
|
||||
|
@ -478,7 +476,7 @@ public class Launcher extends StatefulActivity<LauncherState> implements Launche
|
|||
() -> getStateManager().goToState(NORMAL));
|
||||
|
||||
if (Utilities.ATLEAST_R) {
|
||||
getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_ADJUST_NOTHING);
|
||||
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING);
|
||||
}
|
||||
|
||||
mLifecycleRegistry = new LifecycleRegistry(this);
|
||||
|
@ -556,6 +554,7 @@ public class Launcher extends StatefulActivity<LauncherState> implements Launche
|
|||
}
|
||||
|
||||
private void onIdpChanged(InvariantDeviceProfile idp) {
|
||||
mUserEventDispatcher = null;
|
||||
|
||||
initDeviceProfile(idp);
|
||||
dispatchDeviceProfileChanged();
|
||||
|
@ -911,7 +910,7 @@ public class Launcher extends StatefulActivity<LauncherState> implements Launche
|
|||
mOverlayManager.onActivityStopped(this);
|
||||
}
|
||||
|
||||
logStopAndResume(false /* isResume */);
|
||||
logStopAndResume(Action.Command.STOP);
|
||||
mAppWidgetHost.setListenIfResumed(false);
|
||||
NotificationListener.removeNotificationsChangedListener();
|
||||
}
|
||||
|
@ -933,7 +932,7 @@ public class Launcher extends StatefulActivity<LauncherState> implements Launche
|
|||
@Override
|
||||
@CallSuper
|
||||
protected void onDeferredResumed() {
|
||||
logStopAndResume(true /* isResume */);
|
||||
logStopAndResume(Action.Command.RESUME);
|
||||
|
||||
// Process any items that were added while Launcher was away.
|
||||
ItemInstallQueue.INSTANCE.get(this)
|
||||
|
@ -950,28 +949,32 @@ public class Launcher extends StatefulActivity<LauncherState> implements Launche
|
|||
|
||||
protected void handlePendingActivityRequest() { }
|
||||
|
||||
private void logStopAndResume(boolean isResume) {
|
||||
private void logStopAndResume(int command) {
|
||||
if (mPendingExecutor != null) return;
|
||||
int pageIndex = mWorkspace.isOverlayShown() ? -1 : mWorkspace.getCurrentPage();
|
||||
int statsLogOrdinal = mStateManager.getState().statsLogOrdinal;
|
||||
int containerType = mStateManager.getState().containerType;
|
||||
|
||||
StatsLogManager.EventEnum event;
|
||||
StatsLogManager.StatsLogger logger = getStatsLogManager().logger();
|
||||
if (isResume) {
|
||||
if (command == Action.Command.RESUME) {
|
||||
logger.withSrcState(LAUNCHER_STATE_BACKGROUND)
|
||||
.withDstState(mStateManager.getState().statsLogOrdinal);
|
||||
.withDstState(containerTypeToAtomState(mStateManager.getState().containerType));
|
||||
event = LAUNCHER_ONRESUME;
|
||||
} else { /* command == Action.Command.STOP */
|
||||
logger.withSrcState(mStateManager.getState().statsLogOrdinal)
|
||||
logger.withSrcState(containerTypeToAtomState(mStateManager.getState().containerType))
|
||||
.withDstState(LAUNCHER_STATE_BACKGROUND);
|
||||
event = LAUNCHER_ONSTOP;
|
||||
}
|
||||
|
||||
if (statsLogOrdinal == LAUNCHER_STATE_HOME && mWorkspace != null) {
|
||||
if (containerType == ContainerType.WORKSPACE && mWorkspace != null) {
|
||||
getUserEventDispatcher().logActionCommand(command,
|
||||
containerType, -1, pageIndex);
|
||||
logger.withContainerInfo(LauncherAtom.ContainerInfo.newBuilder()
|
||||
.setWorkspace(
|
||||
LauncherAtom.WorkspaceContainer.newBuilder()
|
||||
.setPageIndex(pageIndex)).build());
|
||||
} else {
|
||||
getUserEventDispatcher().logActionCommand(command, containerType, -1);
|
||||
}
|
||||
logger.log(event);
|
||||
}
|
||||
|
@ -1361,18 +1364,6 @@ public class Launcher extends StatefulActivity<LauncherState> implements Launche
|
|||
closeContextMenu();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object onRetainNonConfigurationInstance() {
|
||||
int width = mDragLayer.getWidth();
|
||||
int height = mDragLayer.getHeight();
|
||||
|
||||
if (width <= 0 || height <= 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return BitmapRenderer.createHardwareBitmap(width, height, mDragLayer::draw);
|
||||
}
|
||||
|
||||
public AllAppsTransitionController getAllAppsController() {
|
||||
return mAllAppsController;
|
||||
}
|
||||
|
@ -1473,6 +1464,11 @@ public class Launcher extends StatefulActivity<LauncherState> implements Launche
|
|||
}
|
||||
|
||||
// Handle HOME_INTENT
|
||||
UserEventDispatcher ued = getUserEventDispatcher();
|
||||
Target target = newContainerTarget(mStateManager.getState().containerType);
|
||||
target.pageIndex = mWorkspace.getCurrentPage();
|
||||
ued.logActionCommand(Action.Command.HOME_INTENT, target,
|
||||
newContainerTarget(ContainerType.WORKSPACE));
|
||||
hideKeyboard();
|
||||
|
||||
if (mLauncherCallbacks != null) {
|
||||
|
@ -2762,40 +2758,4 @@ public class Launcher extends StatefulActivity<LauncherState> implements Launche
|
|||
|
||||
void onLauncherResume();
|
||||
}
|
||||
|
||||
/**
|
||||
* Cross-fades the launcher's updated appearance with its previous appearance.
|
||||
*
|
||||
* This method is used to cross-fade UI updates on activity creation, specifically dark mode
|
||||
* updates.
|
||||
*/
|
||||
private void crossFadeWithPreviousAppearance() {
|
||||
Bitmap previousAppearanceBitmap = (Bitmap) getLastNonConfigurationInstance();
|
||||
|
||||
if (previousAppearanceBitmap == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
ImageView crossFadeHelper = new ImageView(this);
|
||||
|
||||
crossFadeHelper.setImageBitmap(previousAppearanceBitmap);
|
||||
crossFadeHelper.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
|
||||
|
||||
InsettableFrameLayout.LayoutParams layoutParams = new InsettableFrameLayout.LayoutParams(
|
||||
InsettableFrameLayout.LayoutParams.MATCH_PARENT,
|
||||
InsettableFrameLayout.LayoutParams.MATCH_PARENT);
|
||||
|
||||
layoutParams.ignoreInsets = true;
|
||||
|
||||
crossFadeHelper.setLayoutParams(layoutParams);
|
||||
|
||||
getRootView().addView(crossFadeHelper);
|
||||
|
||||
crossFadeHelper
|
||||
.animate()
|
||||
.setDuration(THEME_CROSS_FADE_ANIMATION_DURATION)
|
||||
.alpha(0f)
|
||||
.withEndAction(() -> getRootView().removeView(crossFadeHelper))
|
||||
.start();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -105,7 +105,7 @@ public class LauncherAppState {
|
|||
new Handler().post( () -> mInvariantDeviceProfile.verifyConfigChangedInBackground(context));
|
||||
|
||||
mInstallSessionTracker = InstallSessionHelper.INSTANCE.get(context)
|
||||
.registerInstallTracker(mModel);
|
||||
.registerInstallTracker(mModel, MODEL_EXECUTOR);
|
||||
|
||||
// Register an observer to rebind the notification listener when dots are re-enabled.
|
||||
mNotificationDotsObserver =
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
package com.android.launcher3;
|
||||
|
||||
import static com.android.launcher3.anim.Interpolators.ACCEL_2;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_HOME;
|
||||
import static com.android.launcher3.testing.TestProtocol.ALL_APPS_STATE_ORDINAL;
|
||||
import static com.android.launcher3.testing.TestProtocol.BACKGROUND_APP_STATE_ORDINAL;
|
||||
import static com.android.launcher3.testing.TestProtocol.HINT_STATE_ORDINAL;
|
||||
|
@ -36,6 +35,7 @@ import com.android.launcher3.states.SpringLoadedState;
|
|||
import com.android.launcher3.testing.TestProtocol;
|
||||
import com.android.launcher3.uioverrides.states.AllAppsState;
|
||||
import com.android.launcher3.uioverrides.states.OverviewState;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
|
@ -97,7 +97,7 @@ public abstract class LauncherState implements BaseState<LauncherState> {
|
|||
* TODO: Create a separate class for NORMAL state.
|
||||
*/
|
||||
public static final LauncherState NORMAL = new LauncherState(NORMAL_STATE_ORDINAL,
|
||||
LAUNCHER_STATE_HOME,
|
||||
ContainerType.WORKSPACE,
|
||||
FLAG_DISABLE_RESTORE | FLAG_WORKSPACE_ICONS_CAN_BE_DRAGGED | FLAG_HIDE_BACK_BUTTON |
|
||||
FLAG_HAS_SYS_UI_SCRIM) {
|
||||
@Override
|
||||
|
@ -126,9 +126,9 @@ public abstract class LauncherState implements BaseState<LauncherState> {
|
|||
public final int ordinal;
|
||||
|
||||
/**
|
||||
* Used for {@link com.android.launcher3.logging.StatsLogManager}
|
||||
* Used for containerType in {@link com.android.launcher3.logging.UserEventDispatcher}
|
||||
*/
|
||||
public final int statsLogOrdinal;
|
||||
public final int containerType;
|
||||
|
||||
/**
|
||||
* True if the state has overview panel visible.
|
||||
|
@ -137,8 +137,8 @@ public abstract class LauncherState implements BaseState<LauncherState> {
|
|||
|
||||
private final int mFlags;
|
||||
|
||||
public LauncherState(int id, int statsLogOrdinal, int flags) {
|
||||
this.statsLogOrdinal = statsLogOrdinal;
|
||||
public LauncherState(int id, int containerType, int flags) {
|
||||
this.containerType = containerType;
|
||||
this.mFlags = flags;
|
||||
this.overviewUi = (flags & FLAG_OVERVIEW_UI) != 0;
|
||||
this.ordinal = id;
|
||||
|
|
|
@ -37,11 +37,14 @@ import com.android.launcher3.Launcher.OnResumeCallback;
|
|||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.dragndrop.DragOptions;
|
||||
import com.android.launcher3.logging.FileLog;
|
||||
import com.android.launcher3.logging.LoggerUtils;
|
||||
import com.android.launcher3.logging.StatsLogManager;
|
||||
import com.android.launcher3.logging.StatsLogManager.StatsLogger;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.ItemInfoWithIcon;
|
||||
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ControlType;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
|
||||
import com.android.launcher3.util.PackageManagerHelper;
|
||||
import com.android.launcher3.util.Themes;
|
||||
|
||||
|
@ -131,6 +134,19 @@ public class SecondaryDropTarget extends ButtonDropTarget implements OnAlarmList
|
|||
return mCurrentAccessibilityAction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Target getDropTargetForLogging() {
|
||||
Target t = LoggerUtils.newTarget(Target.Type.CONTROL);
|
||||
if (mCurrentAccessibilityAction == UNINSTALL) {
|
||||
t.controlType = ControlType.UNINSTALL_TARGET;
|
||||
} else if (mCurrentAccessibilityAction == DISMISS_PREDICTION) {
|
||||
t.controlType = ControlType.DISMISS_PREDICTION;
|
||||
} else {
|
||||
t.controlType = ControlType.SETTINGS_BUTTON;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsDrop(ItemInfo info) {
|
||||
return supportsAccessibilityDrop(info, getViewUnderDrag(info));
|
||||
|
|
|
@ -25,11 +25,8 @@ import android.content.pm.PackageManager;
|
|||
import android.os.UserHandle;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.annotation.WorkerThread;
|
||||
|
||||
import com.android.launcher3.model.ItemInstallQueue;
|
||||
import com.android.launcher3.pm.InstallSessionHelper;
|
||||
import com.android.launcher3.util.Executors;
|
||||
|
||||
/**
|
||||
* BroadcastReceiver to handle session commit intent.
|
||||
|
@ -41,11 +38,6 @@ public class SessionCommitReceiver extends BroadcastReceiver {
|
|||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
Executors.MODEL_EXECUTOR.execute(() -> processIntent(context, intent));
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private static void processIntent(Context context, Intent intent) {
|
||||
if (!isEnabled(context)) {
|
||||
// User has decided to not add icons on homescreen.
|
||||
return;
|
||||
|
|
|
@ -133,10 +133,6 @@ public final class Utilities {
|
|||
public static final String EXTRA_WALLPAPER_OFFSET = "com.android.launcher3.WALLPAPER_OFFSET";
|
||||
public static final String EXTRA_WALLPAPER_FLAVOR = "com.android.launcher3.WALLPAPER_FLAVOR";
|
||||
|
||||
// An intent extra to indicate the launch source by launcher.
|
||||
public static final String EXTRA_WALLPAPER_LAUNCH_SOURCE =
|
||||
"com.android.wallpaper.LAUNCH_SOURCE";
|
||||
|
||||
public static boolean IS_RUNNING_IN_TEST_HARNESS =
|
||||
ActivityManager.isRunningInTestHarness();
|
||||
|
||||
|
|
|
@ -85,6 +85,7 @@ import com.android.launcher3.icons.BitmapRenderer;
|
|||
import com.android.launcher3.logger.LauncherAtom;
|
||||
import com.android.launcher3.logging.StatsLogManager;
|
||||
import com.android.launcher3.logging.StatsLogManager.LauncherEvent;
|
||||
import com.android.launcher3.logging.UserEventDispatcher;
|
||||
import com.android.launcher3.model.data.AppInfo;
|
||||
import com.android.launcher3.model.data.FolderInfo;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
|
@ -96,6 +97,8 @@ import com.android.launcher3.statemanager.StateManager;
|
|||
import com.android.launcher3.statemanager.StateManager.StateHandler;
|
||||
import com.android.launcher3.states.StateAnimationConfig;
|
||||
import com.android.launcher3.touch.WorkspaceTouchListener;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
||||
import com.android.launcher3.util.Executors;
|
||||
import com.android.launcher3.util.IntArray;
|
||||
import com.android.launcher3.util.IntSparseArrayMap;
|
||||
|
@ -1001,6 +1004,8 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
|||
public void onOverlayScrollChanged(float scroll) {
|
||||
if (Float.compare(scroll, 1f) == 0) {
|
||||
if (!mOverlayShown) {
|
||||
mLauncher.getUserEventDispatcher().logActionOnContainer(Action.Touch.SWIPE,
|
||||
Action.Direction.LEFT, ContainerType.WORKSPACE, 0);
|
||||
mLauncher.getStatsLogManager().logger()
|
||||
.withSrcState(LAUNCHER_STATE_HOME)
|
||||
.withDstState(LAUNCHER_STATE_HOME)
|
||||
|
@ -1015,16 +1020,20 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
|||
// Not announcing the overlay page for accessibility since it announces itself.
|
||||
} else if (Float.compare(scroll, 0f) == 0) {
|
||||
if (mOverlayShown) {
|
||||
// TODO: this is logged unnecessarily on home gesture.
|
||||
mLauncher.getStatsLogManager().logger()
|
||||
.withSrcState(LAUNCHER_STATE_HOME)
|
||||
.withDstState(LAUNCHER_STATE_HOME)
|
||||
.withContainerInfo(LauncherAtom.ContainerInfo.newBuilder()
|
||||
.setWorkspace(
|
||||
LauncherAtom.WorkspaceContainer.newBuilder()
|
||||
.setPageIndex(-1))
|
||||
.build())
|
||||
.log(LAUNCHER_SWIPERIGHT);
|
||||
UserEventDispatcher ued = mLauncher.getUserEventDispatcher();
|
||||
if (!ued.isPreviousHomeGesture()) {
|
||||
mLauncher.getUserEventDispatcher().logActionOnContainer(Action.Touch.SWIPE,
|
||||
Action.Direction.RIGHT, ContainerType.WORKSPACE, -1);
|
||||
mLauncher.getStatsLogManager().logger()
|
||||
.withSrcState(LAUNCHER_STATE_HOME)
|
||||
.withDstState(LAUNCHER_STATE_HOME)
|
||||
.withContainerInfo(LauncherAtom.ContainerInfo.newBuilder()
|
||||
.setWorkspace(
|
||||
LauncherAtom.WorkspaceContainer.newBuilder()
|
||||
.setPageIndex(-1))
|
||||
.build())
|
||||
.log(LAUNCHER_SWIPERIGHT);
|
||||
}
|
||||
} else if (Float.compare(mOverlayTranslation, 0f) != 0) {
|
||||
// When arriving to 0 overscroll from non-zero overscroll, announce page for
|
||||
// accessibility since default announcements were disabled while in overscroll
|
||||
|
@ -1115,8 +1124,12 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
|||
protected void notifyPageSwitchListener(int prevPage) {
|
||||
super.notifyPageSwitchListener(prevPage);
|
||||
if (prevPage != mCurrentPage) {
|
||||
int swipeDirection = (prevPage < mCurrentPage)
|
||||
? Action.Direction.RIGHT : Action.Direction.LEFT;
|
||||
StatsLogManager.EventEnum event = (prevPage < mCurrentPage)
|
||||
? LAUNCHER_SWIPERIGHT : LAUNCHER_SWIPELEFT;
|
||||
mLauncher.getUserEventDispatcher().logActionOnContainer(Action.Touch.SWIPE,
|
||||
swipeDirection, ContainerType.WORKSPACE, prevPage);
|
||||
mLauncher.getStatsLogManager().logger()
|
||||
.withSrcState(LAUNCHER_STATE_HOME)
|
||||
.withDstState(LAUNCHER_STATE_HOME)
|
||||
|
@ -1162,6 +1175,13 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
|||
computeScrollHelper(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void determineScrollingStart(MotionEvent ev, float touchSlopScale) {
|
||||
if (!isSwitchingState()) {
|
||||
super.determineScrollingStart(ev, touchSlopScale);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void announceForAccessibility(CharSequence text) {
|
||||
// Don't announce if apps is on top of us.
|
||||
|
|
|
@ -130,16 +130,12 @@ public interface WorkspaceLayoutManager {
|
|||
}
|
||||
|
||||
child.setHapticFeedbackEnabled(false);
|
||||
child.setOnLongClickListener(getWorkspaceChildOnLongClickListener());
|
||||
child.setOnLongClickListener(ItemLongClickListener.INSTANCE_WORKSPACE);
|
||||
if (child instanceof DropTarget) {
|
||||
onAddDropTarget((DropTarget) child);
|
||||
}
|
||||
}
|
||||
|
||||
default View.OnLongClickListener getWorkspaceChildOnLongClickListener() {
|
||||
return ItemLongClickListener.INSTANCE_WORKSPACE;
|
||||
}
|
||||
|
||||
Hotseat getHotseat();
|
||||
|
||||
CellLayout getScreenWithId(int screenId);
|
||||
|
|
|
@ -92,14 +92,10 @@ public class AllAppsGridAdapter extends
|
|||
|
||||
public static final int VIEW_TYPE_SEARCH_SLICE = 1 << 9;
|
||||
|
||||
public static final int VIEW_TYPE_SEARCH_ICON_ROW = 1 << 10;
|
||||
public static final int VIEW_TYPE_SEARCH_SHORTCUT = 1 << 10;
|
||||
|
||||
public static final int VIEW_TYPE_SEARCH_PEOPLE = 1 << 11;
|
||||
|
||||
public static final int VIEW_TYPE_SEARCH_THUMBNAIL = 1 << 12;
|
||||
|
||||
public static final int VIEW_TYPE_SEARCH_SUGGEST = 1 << 13;
|
||||
|
||||
// Common view type masks
|
||||
public static final int VIEW_TYPE_MASK_DIVIDER = VIEW_TYPE_ALL_APPS_DIVIDER;
|
||||
public static final int VIEW_TYPE_MASK_ICON = VIEW_TYPE_ICON;
|
||||
|
@ -190,9 +186,7 @@ public class AllAppsGridAdapter extends
|
|||
|| viewType == VIEW_TYPE_SEARCH_SLICE
|
||||
|| viewType == VIEW_TYPE_SEARCH_ROW
|
||||
|| viewType == VIEW_TYPE_SEARCH_PEOPLE
|
||||
|| viewType == VIEW_TYPE_SEARCH_THUMBNAIL
|
||||
|| viewType == VIEW_TYPE_SEARCH_ICON_ROW
|
||||
|| viewType == VIEW_TYPE_SEARCH_SUGGEST;
|
||||
|| viewType == VIEW_TYPE_SEARCH_SHORTCUT;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -203,7 +197,6 @@ public class AllAppsGridAdapter extends
|
|||
*/
|
||||
public static class AdapterItemWithPayload<T> extends AdapterItem {
|
||||
private T mPayload;
|
||||
private String mSearchSessionId;
|
||||
private AllAppsSearchPlugin mPlugin;
|
||||
private IntConsumer mSelectionHandler;
|
||||
|
||||
|
@ -225,14 +218,6 @@ public class AllAppsGridAdapter extends
|
|||
mSelectionHandler = runnable;
|
||||
}
|
||||
|
||||
public void setSearchSessionId(String searchSessionId) {
|
||||
mSearchSessionId = searchSessionId;
|
||||
}
|
||||
|
||||
public String getSearchSessionId() {
|
||||
return mSearchSessionId;
|
||||
}
|
||||
|
||||
public IntConsumer getSelectionHandler() {
|
||||
return mSelectionHandler;
|
||||
}
|
||||
|
@ -240,8 +225,6 @@ public class AllAppsGridAdapter extends
|
|||
public T getPayload() {
|
||||
return mPayload;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -324,21 +307,15 @@ public class AllAppsGridAdapter extends
|
|||
|
||||
@Override
|
||||
public int getSpanSize(int position) {
|
||||
int viewType = mApps.getAdapterItems().get(position).viewType;
|
||||
if (isIconViewType(viewType)) {
|
||||
return 1 * SPAN_MULTIPLIER;
|
||||
} else if (viewType == VIEW_TYPE_SEARCH_THUMBNAIL) {
|
||||
return mAppsPerRow;
|
||||
if (isIconViewType(mApps.getAdapterItems().get(position).viewType)) {
|
||||
return 1;
|
||||
} else {
|
||||
// Section breaks span the full width
|
||||
return mAppsPerRow * SPAN_MULTIPLIER;
|
||||
return mAppsPerRow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// multiplier to support adapter item column count that is not mAppsPerRow.
|
||||
public static final int SPAN_MULTIPLIER = 3;
|
||||
|
||||
private final BaseDraggingActivity mLauncher;
|
||||
private final LayoutInflater mLayoutInflater;
|
||||
private final AlphabeticalAppsList mApps;
|
||||
|
@ -375,7 +352,7 @@ public class AllAppsGridAdapter extends
|
|||
|
||||
public void setAppsPerRow(int appsPerRow) {
|
||||
mAppsPerRow = appsPerRow;
|
||||
mGridLayoutMgr.setSpanCount(mAppsPerRow * SPAN_MULTIPLIER);
|
||||
mGridLayoutMgr.setSpanCount(mAppsPerRow);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -461,18 +438,12 @@ public class AllAppsGridAdapter extends
|
|||
case VIEW_TYPE_SEARCH_SLICE:
|
||||
return new ViewHolder(mLayoutInflater.inflate(
|
||||
R.layout.search_result_slice, parent, false));
|
||||
case VIEW_TYPE_SEARCH_ICON_ROW:
|
||||
case VIEW_TYPE_SEARCH_SHORTCUT:
|
||||
return new ViewHolder(mLayoutInflater.inflate(
|
||||
R.layout.search_result_icon_row, parent, false));
|
||||
R.layout.search_result_shortcut, parent, false));
|
||||
case VIEW_TYPE_SEARCH_PEOPLE:
|
||||
return new ViewHolder(mLayoutInflater.inflate(
|
||||
R.layout.search_result_people_item, parent, false));
|
||||
case VIEW_TYPE_SEARCH_THUMBNAIL:
|
||||
return new ViewHolder(mLayoutInflater.inflate(
|
||||
R.layout.search_result_thumbnail, parent, false));
|
||||
case VIEW_TYPE_SEARCH_SUGGEST:
|
||||
return new ViewHolder(mLayoutInflater.inflate(
|
||||
R.layout.search_result_suggest, parent, false));
|
||||
default:
|
||||
throw new RuntimeException("Unexpected view type");
|
||||
}
|
||||
|
@ -493,27 +464,24 @@ public class AllAppsGridAdapter extends
|
|||
//TODO: replace with custom TopHitBubbleTextView with support for both shortcut
|
||||
// and apps
|
||||
if (adapterItem instanceof AdapterItemWithPayload) {
|
||||
AdapterItemWithPayload item = (AdapterItemWithPayload) adapterItem;
|
||||
item.setSelectionHandler(type -> {
|
||||
AdapterItemWithPayload withPayload = (AdapterItemWithPayload) adapterItem;
|
||||
IntConsumer selectionHandler = type -> {
|
||||
SearchTargetEvent e = new SearchTargetEvent(SearchTarget.ItemType.APP,
|
||||
type, item.position, item.getSearchSessionId());
|
||||
type);
|
||||
e.bundle = HeroSearchResultView.getAppBundle(info);
|
||||
if (item.getPlugin() != null) {
|
||||
item.getPlugin().notifySearchTargetEvent(e);
|
||||
if (withPayload.getPlugin() != null) {
|
||||
withPayload.getPlugin().notifySearchTargetEvent(e);
|
||||
}
|
||||
});
|
||||
};
|
||||
icon.setOnClickListener(view -> {
|
||||
item.getSelectionHandler().accept(SearchTargetEvent.SELECT);
|
||||
selectionHandler.accept(SearchTargetEvent.SELECT);
|
||||
mOnIconClickListener.onClick(view);
|
||||
});
|
||||
icon.setOnLongClickListener(view -> {
|
||||
item.getSelectionHandler().accept(SearchTargetEvent.SELECT);
|
||||
selectionHandler.accept(SearchTargetEvent.LONG_PRESS);
|
||||
return mOnIconLongClickListener.onLongClick(view);
|
||||
});
|
||||
}
|
||||
else {
|
||||
icon.setOnClickListener(mOnIconClickListener);
|
||||
icon.setOnLongClickListener(mOnIconLongClickListener);
|
||||
withPayload.setSelectionHandler(selectionHandler);
|
||||
}
|
||||
break;
|
||||
case VIEW_TYPE_EMPTY_SEARCH:
|
||||
|
@ -532,22 +500,20 @@ public class AllAppsGridAdapter extends
|
|||
break;
|
||||
case VIEW_TYPE_SEARCH_SLICE:
|
||||
SliceView sliceView = (SliceView) holder.itemView;
|
||||
AdapterItemWithPayload<Uri> slicePayload =
|
||||
AdapterItemWithPayload<Uri> item =
|
||||
(AdapterItemWithPayload<Uri>) mApps.getAdapterItems().get(position);
|
||||
sliceView.setOnSliceActionListener((info1, s) -> {
|
||||
if (slicePayload.getPlugin() != null) {
|
||||
if (item.getPlugin() != null) {
|
||||
SearchTargetEvent searchTargetEvent = new SearchTargetEvent(
|
||||
SearchTarget.ItemType.SETTINGS_SLICE,
|
||||
SearchTargetEvent.CHILD_SELECT, slicePayload.position,
|
||||
slicePayload.getSearchSessionId());
|
||||
SearchTargetEvent.CHILD_SELECT);
|
||||
searchTargetEvent.bundle = new Bundle();
|
||||
searchTargetEvent.bundle.putParcelable("uri", slicePayload.getPayload());
|
||||
slicePayload.getPlugin().notifySearchTargetEvent(searchTargetEvent);
|
||||
searchTargetEvent.bundle.putParcelable("uri", item.getPayload());
|
||||
item.getPlugin().notifySearchTargetEvent(searchTargetEvent);
|
||||
}
|
||||
});
|
||||
try {
|
||||
LiveData<Slice> liveData = SliceLiveData.fromUri(mLauncher,
|
||||
slicePayload.getPayload());
|
||||
LiveData<Slice> liveData = SliceLiveData.fromUri(mLauncher, item.getPayload());
|
||||
liveData.observe((Launcher) mLauncher, sliceView);
|
||||
sliceView.setTag(liveData);
|
||||
} catch (Exception ignored) {
|
||||
|
@ -557,14 +523,11 @@ public class AllAppsGridAdapter extends
|
|||
case VIEW_TYPE_SEARCH_ROW_WITH_BUTTON:
|
||||
case VIEW_TYPE_SEARCH_HERO_APP:
|
||||
case VIEW_TYPE_SEARCH_ROW:
|
||||
case VIEW_TYPE_SEARCH_ICON_ROW:
|
||||
case VIEW_TYPE_SEARCH_SHORTCUT:
|
||||
case VIEW_TYPE_SEARCH_PEOPLE:
|
||||
case VIEW_TYPE_SEARCH_THUMBNAIL:
|
||||
case VIEW_TYPE_SEARCH_SUGGEST:
|
||||
AdapterItemWithPayload item =
|
||||
(AdapterItemWithPayload) mApps.getAdapterItems().get(position);
|
||||
PayloadResultHandler payloadResultView = (PayloadResultHandler) holder.itemView;
|
||||
payloadResultView.setup(item);
|
||||
payloadResultView.applyAdapterInfo(
|
||||
(AdapterItemWithPayload) mApps.getAdapterItems().get(position));
|
||||
break;
|
||||
case VIEW_TYPE_ALL_APPS_DIVIDER:
|
||||
// nothing to do
|
||||
|
@ -578,8 +541,8 @@ public class AllAppsGridAdapter extends
|
|||
if (!FeatureFlags.ENABLE_DEVICE_SEARCH.get()) return;
|
||||
if (holder.itemView instanceof BubbleTextView) {
|
||||
BubbleTextView icon = (BubbleTextView) holder.itemView;
|
||||
icon.setOnClickListener(null);
|
||||
icon.setOnLongClickListener(null);
|
||||
icon.setOnClickListener(mOnIconClickListener);
|
||||
icon.setOnLongClickListener(mOnIconLongClickListener);
|
||||
} else if (holder.itemView instanceof SliceView) {
|
||||
SliceView sliceView = (SliceView) holder.itemView;
|
||||
sliceView.setOnSliceActionListener(null);
|
||||
|
@ -590,6 +553,7 @@ public class AllAppsGridAdapter extends
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onFailedToRecycleView(ViewHolder holder) {
|
||||
// Always recycle and we will reset the view when it is bound
|
||||
|
|
|
@ -19,6 +19,8 @@ import static android.view.View.MeasureSpec.EXACTLY;
|
|||
import static android.view.View.MeasureSpec.UNSPECIFIED;
|
||||
import static android.view.View.MeasureSpec.makeMeasureSpec;
|
||||
|
||||
import static com.android.launcher3.logging.LoggerUtils.newContainerTarget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Canvas;
|
||||
|
@ -36,6 +38,10 @@ import com.android.launcher3.DeviceProfile;
|
|||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.allapps.AllAppsGridAdapter.AppsGridLayoutManager;
|
||||
import com.android.launcher3.logging.StatsLogUtils.LogContainerProvider;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
|
||||
import com.android.launcher3.views.RecyclerViewFastScroller;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -44,7 +50,7 @@ import java.util.List;
|
|||
/**
|
||||
* A RecyclerView with custom fast scroll support for the all apps view.
|
||||
*/
|
||||
public class AllAppsRecyclerView extends BaseRecyclerView {
|
||||
public class AllAppsRecyclerView extends BaseRecyclerView implements LogContainerProvider {
|
||||
|
||||
private AlphabeticalAppsList mApps;
|
||||
private final int mNumAppsPerRow;
|
||||
|
@ -170,6 +176,13 @@ public class AllAppsRecyclerView extends BaseRecyclerView {
|
|||
mAutoSizedOverlays.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillInLogContainerData(ItemInfo childInfo, Target child,
|
||||
ArrayList<Target> parents) {
|
||||
parents.add(newContainerTarget(
|
||||
getApps().hasFilter() ? ContainerType.SEARCHRESULT : ContainerType.ALLAPPS));
|
||||
}
|
||||
|
||||
public void onSearchResultsChanged() {
|
||||
// Always scroll the view to the top so the user can see the changed results
|
||||
scrollToTop();
|
||||
|
|
|
@ -18,6 +18,8 @@ package com.android.launcher3.allapps;
|
|||
|
||||
import static com.android.launcher3.LauncherState.NORMAL;
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||
import static com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType.HOTSEAT;
|
||||
import static com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType.PREDICTION;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorInflater;
|
||||
|
@ -118,10 +120,10 @@ public class DiscoveryBounce extends AbstractFloatingView {
|
|||
return (type & TYPE_DISCOVERY_BOUNCE) != 0;
|
||||
}
|
||||
|
||||
private void show() {
|
||||
private void show(int containerType) {
|
||||
mIsOpen = true;
|
||||
mLauncher.getDragLayer().addView(this);
|
||||
// TODO: add WW log for discovery bounce tip show event.
|
||||
mLauncher.getUserEventDispatcher().logActionBounceTip(containerType);
|
||||
}
|
||||
|
||||
public static void showForHomeIfNeeded(Launcher launcher) {
|
||||
|
@ -144,7 +146,7 @@ public class DiscoveryBounce extends AbstractFloatingView {
|
|||
}
|
||||
onboardingPrefs.incrementEventCount(OnboardingPrefs.HOME_BOUNCE_COUNT);
|
||||
|
||||
new DiscoveryBounce(launcher, 0).show();
|
||||
new DiscoveryBounce(launcher, 0).show(HOTSEAT);
|
||||
}
|
||||
|
||||
public static void showForOverviewIfNeeded(Launcher launcher,
|
||||
|
@ -177,7 +179,7 @@ public class DiscoveryBounce extends AbstractFloatingView {
|
|||
onboardingPrefs.incrementEventCount(OnboardingPrefs.SHELF_BOUNCE_COUNT);
|
||||
|
||||
new DiscoveryBounce(launcher, (1 - OVERVIEW.getVerticalProgress(launcher)))
|
||||
.show();
|
||||
.show(PREDICTION);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -35,8 +35,6 @@ import com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItemWithPayload;
|
|||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.util.PackageManagerHelper;
|
||||
import com.android.systemui.plugins.AllAppsSearchPlugin;
|
||||
import com.android.systemui.plugins.shared.SearchTarget;
|
||||
import com.android.systemui.plugins.shared.SearchTargetEvent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -215,44 +213,6 @@ public class AllAppsSearchBarController
|
|||
/**
|
||||
* Updates View using Adapter's payload
|
||||
*/
|
||||
|
||||
default void setup(AdapterItemWithPayload<T> adapterItemWithPayload) {
|
||||
Object[] targetInfo = getTargetInfo();
|
||||
if (targetInfo != null) {
|
||||
targetInfo[0] = adapterItemWithPayload.getSearchSessionId();
|
||||
targetInfo[1] = adapterItemWithPayload.position;
|
||||
}
|
||||
applyAdapterInfo(adapterItemWithPayload);
|
||||
}
|
||||
|
||||
void applyAdapterInfo(AdapterItemWithPayload<T> adapterItemWithPayload);
|
||||
|
||||
/**
|
||||
* Gets object created by {@link PayloadResultHandler#createTargetInfo()}
|
||||
*/
|
||||
Object[] getTargetInfo();
|
||||
|
||||
/**
|
||||
* Creates a wrapper object to hold searchSessionId and item position
|
||||
*/
|
||||
default Object[] createTargetInfo() {
|
||||
return new Object[2];
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a SearchTargetEvent object for a PayloadHandlerView
|
||||
*/
|
||||
default SearchTargetEvent getSearchTargetEvent(SearchTarget.ItemType itemType,
|
||||
int eventType) {
|
||||
Object[] targetInfo = getTargetInfo();
|
||||
if (targetInfo == null) return null;
|
||||
|
||||
String searchSessionId = (String) targetInfo[0];
|
||||
int position = (int) targetInfo[1];
|
||||
return new SearchTargetEvent(itemType, eventType,
|
||||
position, searchSessionId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -73,9 +73,9 @@ public class PendingAnimation implements PropertySetter {
|
|||
addAnimationHoldersRecur(a, mDuration, springProperty, mAnimHolders);
|
||||
}
|
||||
|
||||
public void finish(boolean isSuccess) {
|
||||
public void finish(boolean isSuccess, int logAction) {
|
||||
for (Consumer<EndState> listeners : mEndListeners) {
|
||||
listeners.accept(new EndState(isSuccess));
|
||||
listeners.accept(new EndState(isSuccess, logAction));
|
||||
}
|
||||
mEndListeners.clear();
|
||||
}
|
||||
|
@ -164,7 +164,7 @@ public class PendingAnimation implements PropertySetter {
|
|||
|
||||
/**
|
||||
* Add a listener of receiving the end state.
|
||||
* Note that the listeners are called as a result of calling {@link #finish(boolean)}
|
||||
* Note that the listeners are called as a result of calling {@link #finish(boolean, int)}
|
||||
* and not automatically
|
||||
*/
|
||||
public void addEndListener(Consumer<EndState> listener) {
|
||||
|
@ -173,9 +173,11 @@ public class PendingAnimation implements PropertySetter {
|
|||
|
||||
public static class EndState {
|
||||
public boolean isSuccess;
|
||||
public int logAction;
|
||||
|
||||
public EndState(boolean isSuccess) {
|
||||
public EndState(boolean isSuccess, int logAction) {
|
||||
this.isSuccess = isSuccess;
|
||||
this.logAction = logAction;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,11 +16,10 @@
|
|||
|
||||
package com.android.launcher3.dragndrop;
|
||||
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ADD_EXTERNAL_ITEM_BACK;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ADD_EXTERNAL_ITEM_CANCELLED;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ADD_EXTERNAL_ITEM_DRAGGED;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ADD_EXTERNAL_ITEM_PLACED_AUTOMATICALLY;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ADD_EXTERNAL_ITEM_START;
|
||||
import static com.android.launcher3.logging.LoggerUtils.newCommandAction;
|
||||
import static com.android.launcher3.logging.LoggerUtils.newContainerTarget;
|
||||
import static com.android.launcher3.logging.LoggerUtils.newItemTarget;
|
||||
import static com.android.launcher3.logging.LoggerUtils.newLauncherEvent;
|
||||
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
|
@ -50,10 +49,11 @@ import com.android.launcher3.LauncherAppState;
|
|||
import com.android.launcher3.LauncherAppWidgetHost;
|
||||
import com.android.launcher3.LauncherAppWidgetProviderInfo;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.logging.StatsLogManager;
|
||||
import com.android.launcher3.model.ItemInstallQueue;
|
||||
import com.android.launcher3.model.WidgetItem;
|
||||
import com.android.launcher3.pm.PinRequestHelper;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
||||
import com.android.launcher3.util.InstantAppResolver;
|
||||
import com.android.launcher3.views.BaseDragLayer;
|
||||
import com.android.launcher3.widget.PendingAddShortcutInfo;
|
||||
|
@ -125,7 +125,7 @@ public class AddItemActivity extends BaseActivity implements OnLongClickListener
|
|||
// savedInstanceState is null when the activity is created the first time (i.e., avoids
|
||||
// duplicate logging during rotation)
|
||||
if (savedInstanceState == null) {
|
||||
logCommand(LAUNCHER_ADD_EXTERNAL_ITEM_START);
|
||||
logCommand(Action.Command.ENTRY);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -178,7 +178,6 @@ public class AddItemActivity extends BaseActivity implements OnLongClickListener
|
|||
startActivity(homeIntent,
|
||||
ActivityOptions.makeCustomAnimation(this, 0, android.R.anim.fade_out)
|
||||
.toBundle());
|
||||
logCommand(LAUNCHER_ADD_EXTERNAL_ITEM_DRAGGED);
|
||||
mFinishOnPause = true;
|
||||
return false;
|
||||
}
|
||||
|
@ -241,7 +240,7 @@ public class AddItemActivity extends BaseActivity implements OnLongClickListener
|
|||
* Called when the cancel button is clicked.
|
||||
*/
|
||||
public void onCancelClick(View v) {
|
||||
logCommand(LAUNCHER_ADD_EXTERNAL_ITEM_CANCELLED);
|
||||
logCommand(Action.Command.CANCEL);
|
||||
finish();
|
||||
}
|
||||
|
||||
|
@ -251,7 +250,7 @@ public class AddItemActivity extends BaseActivity implements OnLongClickListener
|
|||
public void onPlaceAutomaticallyClick(View v) {
|
||||
if (mRequest.getRequestType() == PinItemRequest.REQUEST_TYPE_SHORTCUT) {
|
||||
ItemInstallQueue.INSTANCE.get(this).queueItem(mRequest.getShortcutInfo());
|
||||
logCommand(LAUNCHER_ADD_EXTERNAL_ITEM_PLACED_AUTOMATICALLY);
|
||||
logCommand(Action.Command.CONFIRM);
|
||||
mRequest.accept();
|
||||
finish();
|
||||
return;
|
||||
|
@ -275,13 +274,13 @@ public class AddItemActivity extends BaseActivity implements OnLongClickListener
|
|||
.queueItem(mRequest.getAppWidgetProviderInfo(this), widgetId);
|
||||
mWidgetOptions.putInt(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId);
|
||||
mRequest.accept(mWidgetOptions);
|
||||
logCommand(LAUNCHER_ADD_EXTERNAL_ITEM_PLACED_AUTOMATICALLY);
|
||||
logCommand(Action.Command.CONFIRM);
|
||||
finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
logCommand(LAUNCHER_ADD_EXTERNAL_ITEM_BACK);
|
||||
logCommand(Action.Command.BACK);
|
||||
super.onBackPressed();
|
||||
}
|
||||
|
||||
|
@ -321,7 +320,10 @@ public class AddItemActivity extends BaseActivity implements OnLongClickListener
|
|||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
private void logCommand(StatsLogManager.EventEnum command) {
|
||||
getStatsLogManager().logger().log(command);
|
||||
private void logCommand(int command) {
|
||||
getUserEventDispatcher().dispatchUserEvent(newLauncherEvent(
|
||||
newCommandAction(command),
|
||||
newItemTarget(mWidgetCell.getWidgetView(), mInstantAppResolver),
|
||||
newContainerTarget(ContainerType.PINITEM)), null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -206,6 +206,7 @@ public class DragController implements DragDriver.EventListener, TouchController
|
|||
}
|
||||
|
||||
handleMoveEvent(mLastTouch.x, mLastTouch.y);
|
||||
mLauncher.getUserEventDispatcher().resetActionDurationMillis();
|
||||
|
||||
if (!mLauncher.isTouchInProgress() && options.simulatedDndStartPoint == null) {
|
||||
// If it is an internal drag and the touch is already complete, cancel immediately
|
||||
|
@ -543,6 +544,7 @@ public class DragController implements DragDriver.EventListener, TouchController
|
|||
}
|
||||
}
|
||||
final View dropTargetAsView = dropTarget instanceof View ? (View) dropTarget : null;
|
||||
mLauncher.getUserEventDispatcher().logDragNDrop(mDragObject, dropTargetAsView);
|
||||
dispatchDropComplete(dropTargetAsView, accepted);
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ import static com.android.launcher3.LauncherAnimUtils.SPRING_LOADED_EXIT_DELAY;
|
|||
import static com.android.launcher3.LauncherState.NORMAL;
|
||||
import static com.android.launcher3.compat.AccessibilityManagerCompat.sendCustomAccessibilityEvent;
|
||||
import static com.android.launcher3.config.FeatureFlags.ALWAYS_USE_HARDWARE_OPTIMIZATION_FOR_FOLDER_ANIMATIONS;
|
||||
import static com.android.launcher3.logging.LoggerUtils.newContainerTarget;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_FOLDER_CONVERTED_TO_ICON;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_FOLDER_LABEL_UPDATED;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ITEM_DROP_COMPLETED;
|
||||
|
@ -94,6 +95,7 @@ import com.android.launcher3.model.data.FolderInfo.FolderListener;
|
|||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.pageindicators.PageIndicatorDots;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||
import com.android.launcher3.util.Executors;
|
||||
import com.android.launcher3.util.Thunk;
|
||||
import com.android.launcher3.views.ClipPathView;
|
||||
|
@ -597,6 +599,15 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
|
|||
* is played.
|
||||
*/
|
||||
private void animateOpen(List<WorkspaceItemInfo> items, int pageNo) {
|
||||
animateOpen(items, pageNo, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the user folder described by the specified tag. The opening of the folder
|
||||
* is animated relative to the specified View. If the View is null, no animation
|
||||
* is played.
|
||||
*/
|
||||
private void animateOpen(List<WorkspaceItemInfo> items, int pageNo, boolean skipUserEventLog) {
|
||||
Folder openFolder = getOpen(mLauncher);
|
||||
if (openFolder != null && openFolder != this) {
|
||||
// Close any open folder before opening a folder.
|
||||
|
@ -646,6 +657,14 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
|
|||
mState = STATE_OPEN;
|
||||
announceAccessibilityChanges();
|
||||
|
||||
if (!skipUserEventLog) {
|
||||
mLauncher.getUserEventDispatcher().logActionOnItem(
|
||||
LauncherLogProto.Action.Touch.TAP,
|
||||
LauncherLogProto.Action.Direction.NONE,
|
||||
LauncherLogProto.ItemType.FOLDER_ICON, mInfo.cellX, mInfo.cellY);
|
||||
}
|
||||
|
||||
|
||||
mContent.setFocusOnFirstChild();
|
||||
}
|
||||
});
|
||||
|
@ -1494,6 +1513,7 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
|
|||
}
|
||||
|
||||
statsLogger.log(LAUNCHER_FOLDER_LABEL_UPDATED);
|
||||
logFolderLabelState(mFromLabelState, toLabelState);
|
||||
mFolderName.dispatchBackKey();
|
||||
}
|
||||
}
|
||||
|
@ -1624,7 +1644,8 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
|
|||
return true;
|
||||
}
|
||||
} else {
|
||||
// TODO: add ww log if need to gather tap outside to close folder
|
||||
mLauncher.getUserEventDispatcher().logActionTapOutside(
|
||||
newContainerTarget(LauncherLogProto.ContainerType.FOLDER));
|
||||
close(true);
|
||||
return true;
|
||||
}
|
||||
|
@ -1659,6 +1680,17 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
|
|||
return mContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs current folder label info.
|
||||
*
|
||||
* @deprecated This method is only used for log validation and soon will be removed.
|
||||
*/
|
||||
@Deprecated
|
||||
public void logFolderLabelState(FromState fromState, ToState toState) {
|
||||
mLauncher.getUserEventDispatcher()
|
||||
.logLauncherEvent(mInfo.getFolderLabelStateLauncherEvent(fromState, toState));
|
||||
}
|
||||
|
||||
/** Returns the height of the current folder's bottom edge from the bottom of the screen. */
|
||||
private int getHeightFromBottom() {
|
||||
DragLayer.LayoutParams layoutParams = (DragLayer.LayoutParams) getLayoutParams();
|
||||
|
|
|
@ -478,6 +478,7 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel
|
|||
// event is assumed to be folder creation on the server side.
|
||||
.withEditText(newTitle.toString())
|
||||
.log(LAUNCHER_FOLDER_AUTO_LABELED);
|
||||
mFolder.logFolderLabelState(fromState, ToState.TO_SUGGESTION0);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -513,7 +513,8 @@ public class LauncherPreviewRenderer extends ContextThemeWrapper
|
|||
}
|
||||
|
||||
// Setup search view
|
||||
SearchUiManager searchUiManager = mRootView.findViewById(R.id.search_container_all_apps);
|
||||
SearchUiManager searchUiManager =
|
||||
mRootView.findViewById(R.id.search_container_all_apps);
|
||||
mRootView.findViewById(R.id.apps_view).setTranslationY(
|
||||
mDp.heightPx - searchUiManager.getScrollRangeDelta(mInsets));
|
||||
ViewGroup searchView = (ViewGroup) searchUiManager;
|
||||
|
|
|
@ -0,0 +1,190 @@
|
|||
/*
|
||||
* Copyright (C) 2016 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.launcher3.logging;
|
||||
|
||||
import android.util.ArrayMap;
|
||||
import android.util.SparseArray;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.launcher3.ButtonDropTarget;
|
||||
import com.android.launcher3.LauncherSettings;
|
||||
import com.android.launcher3.model.data.AppInfo;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogExtensions.TargetExtension;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ItemType;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.LauncherEvent;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
|
||||
import com.android.launcher3.util.InstantAppResolver;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Helper methods for logging.
|
||||
*/
|
||||
public class LoggerUtils {
|
||||
private static final ArrayMap<Class, SparseArray<String>> sNameCache = new ArrayMap<>();
|
||||
private static final String UNKNOWN = "UNKNOWN";
|
||||
private static final int DEFAULT_PREDICTED_RANK = 10000;
|
||||
private static final String DELIMITER_DOT = "\\.";
|
||||
|
||||
public static String getFieldName(int value, Class c) {
|
||||
SparseArray<String> cache;
|
||||
synchronized (sNameCache) {
|
||||
cache = sNameCache.get(c);
|
||||
if (cache == null) {
|
||||
cache = new SparseArray<>();
|
||||
for (Field f : c.getDeclaredFields()) {
|
||||
if (f.getType() == int.class && Modifier.isStatic(f.getModifiers())) {
|
||||
try {
|
||||
f.setAccessible(true);
|
||||
cache.put(f.getInt(null), f.getName());
|
||||
} catch (IllegalAccessException e) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
sNameCache.put(c, cache);
|
||||
}
|
||||
}
|
||||
String result = cache.get(value);
|
||||
return result != null ? result : UNKNOWN;
|
||||
}
|
||||
|
||||
public static Target newItemTarget(int itemType) {
|
||||
Target t = newTarget(Target.Type.ITEM);
|
||||
t.itemType = itemType;
|
||||
return t;
|
||||
}
|
||||
|
||||
public static Target newItemTarget(View v, InstantAppResolver instantAppResolver) {
|
||||
return (v != null) && (v.getTag() instanceof ItemInfo)
|
||||
? newItemTarget((ItemInfo) v.getTag(), instantAppResolver)
|
||||
: newTarget(Target.Type.ITEM);
|
||||
}
|
||||
|
||||
public static Target newItemTarget(ItemInfo info, InstantAppResolver instantAppResolver) {
|
||||
Target t = newTarget(Target.Type.ITEM);
|
||||
switch (info.itemType) {
|
||||
case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
|
||||
t.itemType = (instantAppResolver != null && info instanceof AppInfo
|
||||
&& instantAppResolver.isInstantApp(((AppInfo) info)))
|
||||
? ItemType.WEB_APP
|
||||
: ItemType.APP_ICON;
|
||||
t.predictedRank = DEFAULT_PREDICTED_RANK;
|
||||
break;
|
||||
case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
|
||||
t.itemType = ItemType.SHORTCUT;
|
||||
t.predictedRank = DEFAULT_PREDICTED_RANK;
|
||||
break;
|
||||
case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
|
||||
t.itemType = ItemType.FOLDER_ICON;
|
||||
break;
|
||||
case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
|
||||
t.itemType = ItemType.WIDGET;
|
||||
break;
|
||||
case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT:
|
||||
t.itemType = ItemType.DEEPSHORTCUT;
|
||||
t.predictedRank = DEFAULT_PREDICTED_RANK;
|
||||
break;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
public static Target newDropTarget(View v) {
|
||||
if (!(v instanceof ButtonDropTarget)) {
|
||||
return newTarget(Target.Type.CONTAINER);
|
||||
}
|
||||
if (v instanceof ButtonDropTarget) {
|
||||
return ((ButtonDropTarget) v).getDropTargetForLogging();
|
||||
}
|
||||
return newTarget(Target.Type.CONTROL);
|
||||
}
|
||||
|
||||
public static Target newTarget(int targetType, TargetExtension extension) {
|
||||
Target t = new Target();
|
||||
t.type = targetType;
|
||||
t.extension = extension;
|
||||
return t;
|
||||
}
|
||||
|
||||
public static Target newTarget(int targetType) {
|
||||
Target t = new Target();
|
||||
t.type = targetType;
|
||||
return t;
|
||||
}
|
||||
|
||||
public static Target newControlTarget(int controlType) {
|
||||
Target t = newTarget(Target.Type.CONTROL);
|
||||
t.controlType = controlType;
|
||||
return t;
|
||||
}
|
||||
|
||||
public static Target newContainerTarget(int containerType) {
|
||||
Target t = newTarget(Target.Type.CONTAINER);
|
||||
t.containerType = containerType;
|
||||
return t;
|
||||
}
|
||||
|
||||
public static Action newAction(int type) {
|
||||
Action a = new Action();
|
||||
a.type = type;
|
||||
return a;
|
||||
}
|
||||
|
||||
public static Action newCommandAction(int command) {
|
||||
Action a = newAction(Action.Type.COMMAND);
|
||||
a.command = command;
|
||||
return a;
|
||||
}
|
||||
|
||||
public static Action newTouchAction(int touch) {
|
||||
Action a = newAction(Action.Type.TOUCH);
|
||||
a.touch = touch;
|
||||
return a;
|
||||
}
|
||||
|
||||
public static LauncherEvent newLauncherEvent(Action action, Target... srcTargets) {
|
||||
LauncherEvent event = new LauncherEvent();
|
||||
event.srcTarget = srcTargets;
|
||||
event.action = action;
|
||||
return event;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates LauncherEvent using Action and ArrayList of Targets
|
||||
*/
|
||||
public static LauncherEvent newLauncherEvent(Action action, ArrayList<Target> targets) {
|
||||
Target[] targetsArray = new Target[targets.size()];
|
||||
targets.toArray(targetsArray);
|
||||
return newLauncherEvent(action, targetsArray);
|
||||
}
|
||||
|
||||
/**
|
||||
* String conversion for only the helpful parts of {@link Object#toString()} method
|
||||
* @param stringToExtract "foo.bar.baz.MyObject@1234"
|
||||
* @return "MyObject@1234"
|
||||
*/
|
||||
public static String extractObjectNameAndAddress(String stringToExtract) {
|
||||
String[] superStringParts = stringToExtract.split(DELIMITER_DOT);
|
||||
if (superStringParts.length == 0) {
|
||||
return "";
|
||||
}
|
||||
return superStringParts[superStringParts.length - 1];
|
||||
}
|
||||
}
|
|
@ -27,6 +27,7 @@ import com.android.launcher3.logger.LauncherAtom.ContainerInfo;
|
|||
import com.android.launcher3.logger.LauncherAtom.FromState;
|
||||
import com.android.launcher3.logger.LauncherAtom.ToState;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.userevent.LauncherLogProto;
|
||||
import com.android.launcher3.util.ResourceBasedOverride;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -50,22 +51,40 @@ public class StatsLogManager implements ResourceBasedOverride {
|
|||
public static final int LAUNCHER_STATE_UNCHANGED = 5;
|
||||
|
||||
/**
|
||||
* Returns event enum based on the two state transition information when swipe
|
||||
* Returns proper launcher state enum for {@link StatsLogManager}(to be removed during
|
||||
* UserEventDispatcher cleanup)
|
||||
*/
|
||||
public static int containerTypeToAtomState(int containerType) {
|
||||
switch (containerType) {
|
||||
case LauncherLogProto.ContainerType.ALLAPPS_VALUE:
|
||||
return LAUNCHER_STATE_ALLAPPS;
|
||||
case LauncherLogProto.ContainerType.OVERVIEW_VALUE:
|
||||
return LAUNCHER_STATE_OVERVIEW;
|
||||
case LauncherLogProto.ContainerType.WORKSPACE_VALUE:
|
||||
return LAUNCHER_STATE_HOME;
|
||||
case LauncherLogProto.ContainerType.APP_VALUE:
|
||||
return LAUNCHER_STATE_BACKGROUND;
|
||||
}
|
||||
return LAUNCHER_STATE_UNSPECIFIED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns event enum based on the two {@link ContainerType} transition information when swipe
|
||||
* gesture happens(to be removed during UserEventDispatcher cleanup).
|
||||
*/
|
||||
public static EventEnum getLauncherAtomEvent(int startState,
|
||||
int targetState, EventEnum fallbackEvent) {
|
||||
if (startState == LAUNCHER_STATE_HOME
|
||||
&& targetState == LAUNCHER_STATE_HOME) {
|
||||
public static EventEnum getLauncherAtomEvent(int startContainerType,
|
||||
int targetContainerType, EventEnum fallbackEvent) {
|
||||
if (startContainerType == LauncherLogProto.ContainerType.WORKSPACE.getNumber()
|
||||
&& targetContainerType == LauncherLogProto.ContainerType.WORKSPACE.getNumber()) {
|
||||
return LAUNCHER_HOME_GESTURE;
|
||||
} else if (startState != LAUNCHER_STATE_OVERVIEW
|
||||
&& targetState == LAUNCHER_STATE_OVERVIEW) {
|
||||
} else if (startContainerType != LauncherLogProto.ContainerType.TASKSWITCHER.getNumber()
|
||||
&& targetContainerType == LauncherLogProto.ContainerType.TASKSWITCHER.getNumber()) {
|
||||
return LAUNCHER_OVERVIEW_GESTURE;
|
||||
} else if (startState != LAUNCHER_STATE_ALLAPPS
|
||||
&& targetState == LAUNCHER_STATE_ALLAPPS) {
|
||||
} else if (startContainerType != LauncherLogProto.ContainerType.ALLAPPS.getNumber()
|
||||
&& targetContainerType == LauncherLogProto.ContainerType.ALLAPPS.getNumber()) {
|
||||
return LAUNCHER_ALLAPPS_OPEN_UP;
|
||||
} else if (startState == LAUNCHER_STATE_ALLAPPS
|
||||
&& targetState != LAUNCHER_STATE_ALLAPPS) {
|
||||
} else if (startContainerType == LauncherLogProto.ContainerType.ALLAPPS.getNumber()
|
||||
&& targetContainerType != LauncherLogProto.ContainerType.ALLAPPS.getNumber()) {
|
||||
return LAUNCHER_ALLAPPS_CLOSE_DOWN;
|
||||
}
|
||||
return fallbackEvent; // TODO fix
|
||||
|
@ -303,38 +322,7 @@ public class StatsLogManager implements ResourceBasedOverride {
|
|||
LAUNCHER_FOLDER_CONVERTED_TO_ICON(628),
|
||||
|
||||
@UiEvent(doc = "A hotseat prediction item was pinned")
|
||||
LAUNCHER_HOTSEAT_PREDICTION_PINNED(629),
|
||||
|
||||
@UiEvent(doc = "Activity to add external item was started")
|
||||
LAUNCHER_ADD_EXTERNAL_ITEM_START(641),
|
||||
|
||||
@UiEvent(doc = "Activity to add external item was cancelled")
|
||||
LAUNCHER_ADD_EXTERNAL_ITEM_CANCELLED(642),
|
||||
|
||||
@UiEvent(doc = "Activity to add external item was backed out")
|
||||
LAUNCHER_ADD_EXTERNAL_ITEM_BACK(643),
|
||||
|
||||
@UiEvent(doc = "Item was placed automatically in external item addition flow")
|
||||
LAUNCHER_ADD_EXTERNAL_ITEM_PLACED_AUTOMATICALLY(644),
|
||||
|
||||
@UiEvent(doc = "Item was dragged in external item addition flow")
|
||||
LAUNCHER_ADD_EXTERNAL_ITEM_DRAGGED(645),
|
||||
|
||||
@UiEvent(doc = "Undo event was tapped.")
|
||||
LAUNCHER_UNDO(648),
|
||||
|
||||
@UiEvent(doc = "Task switcher clear all target was tapped.")
|
||||
LAUNCHER_TASK_CLEAR_ALL(649),
|
||||
|
||||
@UiEvent(doc = "Task preview was long pressed.")
|
||||
LAUNCHER_TASK_PREVIEW_LONGPRESS(650),
|
||||
|
||||
@UiEvent(doc = "User swiped down on workspace (triggering noti shade to open).")
|
||||
LAUNCHER_SWIPE_DOWN_WORKSPACE_NOTISHADE_OPEN(651),
|
||||
|
||||
@UiEvent(doc = "Notification dismissed by swiping right.")
|
||||
LAUNCHER_NOTIFICATION_DISMISSED(652),
|
||||
;
|
||||
LAUNCHER_HOTSEAT_PREDICTION_PINNED(629);
|
||||
|
||||
// ADD MORE
|
||||
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
package com.android.launcher3.logging;
|
||||
|
||||
import android.view.View;
|
||||
import android.view.ViewParent;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class StatsLogUtils {
|
||||
private final static int MAXIMUM_VIEW_HIERARCHY_LEVEL = 5;
|
||||
|
||||
/**
|
||||
* Implemented by containers to provide a container source for a given child.
|
||||
*/
|
||||
public interface LogContainerProvider {
|
||||
|
||||
/**
|
||||
* Populates parent container targets for an item
|
||||
*/
|
||||
void fillInLogContainerData(ItemInfo childInfo, Target child, ArrayList<Target> parents);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively finds the parent of the given child which implements IconLogInfoProvider
|
||||
*/
|
||||
public static LogContainerProvider getLaunchProviderRecursive(@Nullable View v) {
|
||||
ViewParent parent;
|
||||
if (v != null) {
|
||||
parent = v.getParent();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Optimization to only check up to 5 parents.
|
||||
int count = MAXIMUM_VIEW_HIERARCHY_LEVEL;
|
||||
while (parent != null && count-- > 0) {
|
||||
if (parent instanceof LogContainerProvider) {
|
||||
return (LogContainerProvider) parent;
|
||||
} else {
|
||||
parent = parent.getParent();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,373 @@
|
|||
/*
|
||||
* Copyright (C) 2012 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.launcher3.logging;
|
||||
|
||||
import static com.android.launcher3.logging.LoggerUtils.newAction;
|
||||
import static com.android.launcher3.logging.LoggerUtils.newCommandAction;
|
||||
import static com.android.launcher3.logging.LoggerUtils.newContainerTarget;
|
||||
import static com.android.launcher3.logging.LoggerUtils.newDropTarget;
|
||||
import static com.android.launcher3.logging.LoggerUtils.newItemTarget;
|
||||
import static com.android.launcher3.logging.LoggerUtils.newLauncherEvent;
|
||||
import static com.android.launcher3.logging.LoggerUtils.newTarget;
|
||||
import static com.android.launcher3.logging.LoggerUtils.newTouchAction;
|
||||
import static com.android.launcher3.userevent.nano.LauncherLogProto.ItemType;
|
||||
import static com.android.launcher3.userevent.nano.LauncherLogProto.TipType;
|
||||
|
||||
import static java.util.Optional.ofNullable;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.SystemClock;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.DropTarget;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.logging.StatsLogUtils.LogContainerProvider;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.userevent.LauncherLogProto;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.LauncherEvent;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
|
||||
import com.android.launcher3.util.InstantAppResolver;
|
||||
import com.android.launcher3.util.LogConfig;
|
||||
import com.android.launcher3.util.ResourceBasedOverride;
|
||||
|
||||
import com.google.protobuf.InvalidProtocolBufferException;
|
||||
import com.google.protobuf.nano.InvalidProtocolBufferNanoException;
|
||||
import com.google.protobuf.nano.MessageNano;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Manages the creation of {@link LauncherEvent}.
|
||||
* To debug this class, execute following command before side loading a new apk.
|
||||
* <p>
|
||||
* $ adb shell setprop log.tag.UserEvent VERBOSE
|
||||
*/
|
||||
public class UserEventDispatcher implements ResourceBasedOverride {
|
||||
|
||||
private static final String TAG = "UserEvent";
|
||||
private static final boolean IS_VERBOSE = Utilities.isPropertyEnabled(LogConfig.USEREVENT);
|
||||
private static final String UUID_STORAGE = "uuid";
|
||||
|
||||
/**
|
||||
* A factory method for UserEventDispatcher
|
||||
*/
|
||||
public static UserEventDispatcher newInstance(Context context) {
|
||||
SharedPreferences sharedPrefs = Utilities.getDevicePrefs(context);
|
||||
String uuidStr = sharedPrefs.getString(UUID_STORAGE, null);
|
||||
if (uuidStr == null) {
|
||||
uuidStr = UUID.randomUUID().toString();
|
||||
sharedPrefs.edit().putString(UUID_STORAGE, uuidStr).apply();
|
||||
}
|
||||
UserEventDispatcher ued = Overrides.getObject(UserEventDispatcher.class,
|
||||
context.getApplicationContext(), R.string.user_event_dispatcher_class);
|
||||
ued.mUuidStr = uuidStr;
|
||||
ued.mInstantAppResolver = InstantAppResolver.newInstance(context);
|
||||
return ued;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fills in the container data on the given event if the given view is not null.
|
||||
*
|
||||
* @return whether container data was added.
|
||||
*/
|
||||
private boolean fillLogContainer(@Nullable View v, Target child,
|
||||
@Nullable ArrayList<Target> targets) {
|
||||
LogContainerProvider firstParent = StatsLogUtils.getLaunchProviderRecursive(v);
|
||||
if (v == null || !(v.getTag() instanceof ItemInfo) || firstParent == null) {
|
||||
return false;
|
||||
}
|
||||
final ItemInfo itemInfo = (ItemInfo) v.getTag();
|
||||
firstParent.fillInLogContainerData(itemInfo, child, targets);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void onFillInLogContainerData(@NonNull ItemInfo itemInfo, @NonNull Target target,
|
||||
@NonNull ArrayList<Target> targets) {
|
||||
}
|
||||
|
||||
private boolean mSessionStarted;
|
||||
private long mElapsedContainerMillis;
|
||||
private long mElapsedSessionMillis;
|
||||
private long mActionDurationMillis;
|
||||
private String mUuidStr;
|
||||
protected InstantAppResolver mInstantAppResolver;
|
||||
private boolean mAppOrTaskLaunch;
|
||||
private boolean mPreviousHomeGesture;
|
||||
|
||||
private void fillComponentInfo(Target target, ComponentName cn) {
|
||||
if (cn != null) {
|
||||
target.packageNameHash = (mUuidStr + cn.getPackageName()).hashCode();
|
||||
target.componentHash = (mUuidStr + cn.flattenToString()).hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
public void logActionCommand(int command, int srcContainerType, int dstContainerType) {
|
||||
logActionCommand(command, newContainerTarget(srcContainerType),
|
||||
dstContainerType >= 0 ? newContainerTarget(dstContainerType) : null);
|
||||
}
|
||||
|
||||
public void logActionCommand(int command, int srcContainerType, int dstContainerType,
|
||||
int pageIndex) {
|
||||
Target srcTarget = newContainerTarget(srcContainerType);
|
||||
srcTarget.pageIndex = pageIndex;
|
||||
logActionCommand(command, srcTarget,
|
||||
dstContainerType >= 0 ? newContainerTarget(dstContainerType) : null);
|
||||
}
|
||||
|
||||
public void logActionCommand(int command, Target srcTarget, Target dstTarget) {
|
||||
LauncherEvent event = newLauncherEvent(newCommandAction(command), srcTarget);
|
||||
if (command == Action.Command.STOP) {
|
||||
if (mAppOrTaskLaunch || !mSessionStarted) {
|
||||
mSessionStarted = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (dstTarget != null) {
|
||||
event.destTarget = new Target[1];
|
||||
event.destTarget[0] = dstTarget;
|
||||
event.action.isStateChange = true;
|
||||
}
|
||||
dispatchUserEvent(event, null);
|
||||
}
|
||||
|
||||
public void logActionOnControl(int action, int controlType) {
|
||||
logActionOnControl(action, controlType, null);
|
||||
}
|
||||
|
||||
public void logActionOnControl(int action, int controlType, int parentContainerType) {
|
||||
logActionOnControl(action, controlType, null, parentContainerType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs control action with proper parent hierarchy
|
||||
*/
|
||||
public void logActionOnControl(int actionType, int controlType,
|
||||
@Nullable View controlInContainer, int... parentTypes) {
|
||||
Target control = newTarget(Target.Type.CONTROL);
|
||||
control.controlType = controlType;
|
||||
Action action = newAction(actionType);
|
||||
|
||||
ArrayList<Target> targets = makeTargetsList(control);
|
||||
if (controlInContainer != null) {
|
||||
fillLogContainer(controlInContainer, control, targets);
|
||||
}
|
||||
for (int parentContainerType : parentTypes) {
|
||||
if (parentContainerType < 0) continue;
|
||||
targets.add(newContainerTarget(parentContainerType));
|
||||
}
|
||||
LauncherEvent event = newLauncherEvent(action, targets);
|
||||
if (actionType == Action.Touch.DRAGDROP) {
|
||||
event.actionDurationMillis = SystemClock.uptimeMillis() - mActionDurationMillis;
|
||||
}
|
||||
dispatchUserEvent(event, null);
|
||||
}
|
||||
|
||||
public void logActionTapOutside(Target target) {
|
||||
LauncherEvent event = newLauncherEvent(newTouchAction(Action.Type.TOUCH),
|
||||
target);
|
||||
event.action.isOutside = true;
|
||||
dispatchUserEvent(event, null);
|
||||
}
|
||||
|
||||
public void logActionBounceTip(int containerType) {
|
||||
LauncherEvent event = newLauncherEvent(newAction(Action.Type.TIP),
|
||||
newContainerTarget(containerType));
|
||||
event.srcTarget[0].tipType = TipType.BOUNCE;
|
||||
dispatchUserEvent(event, null);
|
||||
}
|
||||
|
||||
public void logActionOnContainer(int action, int dir, int containerType) {
|
||||
logActionOnContainer(action, dir, containerType, 0);
|
||||
}
|
||||
|
||||
public void logActionOnContainer(int action, int dir, int containerType, int pageIndex) {
|
||||
LauncherEvent event = newLauncherEvent(newTouchAction(action),
|
||||
newContainerTarget(containerType));
|
||||
event.action.dir = dir;
|
||||
event.srcTarget[0].pageIndex = pageIndex;
|
||||
dispatchUserEvent(event, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used primarily for swipe up and down when state changes when swipe up happens from the
|
||||
* navbar bezel, the {@param srcChildContainerType} is NAVBAR and
|
||||
* {@param srcParentContainerType} is either one of the two
|
||||
* (1) WORKSPACE: if the launcher is the foreground activity
|
||||
* (2) APP: if another app was the foreground activity
|
||||
*/
|
||||
public void logStateChangeAction(int action, int dir, int downX, int downY,
|
||||
int srcChildTargetType, int srcParentContainerType, int dstContainerType,
|
||||
int pageIndex) {
|
||||
LauncherEvent event;
|
||||
if (srcChildTargetType == ItemType.TASK) {
|
||||
event = newLauncherEvent(newTouchAction(action),
|
||||
newItemTarget(srcChildTargetType),
|
||||
newContainerTarget(srcParentContainerType));
|
||||
} else {
|
||||
event = newLauncherEvent(newTouchAction(action),
|
||||
newContainerTarget(srcChildTargetType),
|
||||
newContainerTarget(srcParentContainerType));
|
||||
}
|
||||
event.destTarget = new Target[1];
|
||||
event.destTarget[0] = newContainerTarget(dstContainerType);
|
||||
event.action.dir = dir;
|
||||
event.action.isStateChange = true;
|
||||
event.srcTarget[0].pageIndex = pageIndex;
|
||||
event.srcTarget[0].spanX = downX;
|
||||
event.srcTarget[0].spanY = downY;
|
||||
dispatchUserEvent(event, null);
|
||||
}
|
||||
|
||||
public void logActionOnItem(int action, int dir, int itemType) {
|
||||
logActionOnItem(action, dir, itemType, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new {@link LauncherEvent} of ITEM target type with input arguments and dispatches it.
|
||||
*
|
||||
* @param touchAction ENUM value of {@link LauncherLogProto.Action.Touch} Action
|
||||
* @param dir ENUM value of {@link LauncherLogProto.Action.Direction} Action
|
||||
* @param itemType ENUM value of {@link LauncherLogProto.ItemType}
|
||||
* @param gridX Nullable X coordinate of item's position on the workspace grid
|
||||
* @param gridY Nullable Y coordinate of item's position on the workspace grid
|
||||
*/
|
||||
public void logActionOnItem(int touchAction, int dir, int itemType,
|
||||
@Nullable Integer gridX, @Nullable Integer gridY) {
|
||||
Target itemTarget = newTarget(Target.Type.ITEM);
|
||||
itemTarget.itemType = itemType;
|
||||
ofNullable(gridX).ifPresent(value -> itemTarget.gridX = value);
|
||||
ofNullable(gridY).ifPresent(value -> itemTarget.gridY = value);
|
||||
LauncherEvent event = newLauncherEvent(newTouchAction(touchAction), itemTarget);
|
||||
event.action.dir = dir;
|
||||
dispatchUserEvent(event, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs proto lite version of LauncherEvent object to clearcut.
|
||||
*/
|
||||
public void logLauncherEvent(
|
||||
com.android.launcher3.userevent.LauncherLogProto.LauncherEvent launcherEvent) {
|
||||
|
||||
if (mPreviousHomeGesture) {
|
||||
mPreviousHomeGesture = false;
|
||||
}
|
||||
mAppOrTaskLaunch = false;
|
||||
launcherEvent.toBuilder()
|
||||
.setElapsedContainerMillis(SystemClock.uptimeMillis() - mElapsedContainerMillis)
|
||||
.setElapsedSessionMillis(
|
||||
SystemClock.uptimeMillis() - mElapsedSessionMillis).build();
|
||||
try {
|
||||
dispatchUserEvent(LauncherEvent.parseFrom(launcherEvent.toByteArray()), null);
|
||||
} catch (InvalidProtocolBufferNanoException e) {
|
||||
throw new RuntimeException("Cannot convert LauncherEvent from Lite to Nano version.");
|
||||
}
|
||||
}
|
||||
|
||||
public void logDeepShortcutsOpen(View icon) {
|
||||
ItemInfo info = (ItemInfo) icon.getTag();
|
||||
Target child = newItemTarget(info, mInstantAppResolver);
|
||||
ArrayList<Target> targets = makeTargetsList(child);
|
||||
fillLogContainer(icon, child, targets);
|
||||
dispatchUserEvent(newLauncherEvent(newTouchAction(Action.Touch.TAP), targets), null);
|
||||
}
|
||||
|
||||
public void logDragNDrop(DropTarget.DragObject dragObj, View dropTargetAsView) {
|
||||
Target srcChild = newItemTarget(dragObj.originalDragInfo, mInstantAppResolver);
|
||||
ArrayList<Target> srcTargets = makeTargetsList(srcChild);
|
||||
|
||||
|
||||
Target destChild = newItemTarget(dragObj.originalDragInfo, mInstantAppResolver);
|
||||
ArrayList<Target> destTargets = makeTargetsList(destChild);
|
||||
|
||||
//dragObj.dragSource.fillInLogContainerData(dragObj.originalDragInfo, srcChild, srcTargets);
|
||||
if (dropTargetAsView instanceof LogContainerProvider) {
|
||||
((LogContainerProvider) dropTargetAsView).fillInLogContainerData(dragObj.dragInfo,
|
||||
destChild, destTargets);
|
||||
}
|
||||
else {
|
||||
destTargets.add(newDropTarget(dropTargetAsView));
|
||||
}
|
||||
LauncherEvent event = newLauncherEvent(newTouchAction(Action.Touch.DRAGDROP), srcTargets);
|
||||
Target[] destTargetsArray = new Target[destTargets.size()];
|
||||
destTargets.toArray(destTargetsArray);
|
||||
event.destTarget = destTargetsArray;
|
||||
|
||||
event.actionDurationMillis = SystemClock.uptimeMillis() - mActionDurationMillis;
|
||||
dispatchUserEvent(event, null);
|
||||
}
|
||||
|
||||
public final void startSession() {
|
||||
mSessionStarted = true;
|
||||
mElapsedSessionMillis = SystemClock.uptimeMillis();
|
||||
mElapsedContainerMillis = SystemClock.uptimeMillis();
|
||||
}
|
||||
|
||||
public final void setPreviousHomeGesture(boolean homeGesture) {
|
||||
mPreviousHomeGesture = homeGesture;
|
||||
}
|
||||
|
||||
public final boolean isPreviousHomeGesture() {
|
||||
return mPreviousHomeGesture;
|
||||
}
|
||||
|
||||
public final void resetActionDurationMillis() {
|
||||
mActionDurationMillis = SystemClock.uptimeMillis();
|
||||
}
|
||||
|
||||
public void dispatchUserEvent(LauncherEvent ev, Intent intent) {
|
||||
if (mPreviousHomeGesture) {
|
||||
mPreviousHomeGesture = false;
|
||||
}
|
||||
mAppOrTaskLaunch = false;
|
||||
ev.elapsedContainerMillis = SystemClock.uptimeMillis() - mElapsedContainerMillis;
|
||||
ev.elapsedSessionMillis = SystemClock.uptimeMillis() - mElapsedSessionMillis;
|
||||
if (!IS_VERBOSE) {
|
||||
return;
|
||||
}
|
||||
LauncherLogProto.LauncherEvent liteLauncherEvent;
|
||||
try {
|
||||
liteLauncherEvent =
|
||||
LauncherLogProto.LauncherEvent.parseFrom(MessageNano.toByteArray(ev));
|
||||
} catch (InvalidProtocolBufferException e) {
|
||||
throw new RuntimeException("Cannot parse LauncherEvent from Nano to Lite version");
|
||||
}
|
||||
Log.d(TAG, liteLauncherEvent.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an ArrayList with targets
|
||||
*/
|
||||
public static ArrayList<Target> makeTargetsList(Target... targets) {
|
||||
ArrayList<Target> result = new ArrayList<>();
|
||||
for (Target target : targets) {
|
||||
result.add(target);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue