Merging from ub-launcher3-rvc-qpr-dev @ build 6690853
Bug:150504032 Test: manual, presubmit on the source branch x20/teams/android-launcher/merge/ub-launcher3-rvc-qpr-dev-rvc-qpr-dev_6690853.html Change-Id: Ie86b0a2e0d82646a0c3d44a0214cbb985435320d Merged-In: Ibff46b3ef7ff89accb459db323f31179adb4ef21
This commit is contained in:
commit
65b16d6db2
|
@ -46,9 +46,6 @@
|
|||
<uses-permission android:name="android.permission.READ_DEVICE_CONFIG" />
|
||||
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
|
||||
|
||||
<!-- TODO(b/150802536): Enabled only for ENABLE_FIXED_ROTATION_TRANSFORM feature flag -->
|
||||
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"/>
|
||||
|
||||
<!--
|
||||
Permissions required for read/write access to the workspace data. These permission name
|
||||
should not conflict with that defined in other apps, as such an app should embed its package
|
||||
|
@ -86,6 +83,7 @@
|
|||
<receiver
|
||||
android:name="com.android.launcher3.InstallShortcutReceiver"
|
||||
android:permission="com.android.launcher.permission.INSTALL_SHORTCUT"
|
||||
android:exported="true"
|
||||
android:enabled="@bool/enable_install_shortcut_api" >
|
||||
<intent-filter>
|
||||
<action android:name="com.android.launcher.action.INSTALL_SHORTCUT" />
|
||||
|
@ -94,14 +92,16 @@
|
|||
|
||||
<!-- Intent received when a session is committed -->
|
||||
<receiver
|
||||
android:name="com.android.launcher3.SessionCommitReceiver" >
|
||||
android:name="com.android.launcher3.SessionCommitReceiver"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.content.pm.action.SESSION_COMMITTED" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<!-- Intent received used to initialize a restored widget -->
|
||||
<receiver android:name="com.android.launcher3.AppWidgetsRestoredReceiver" >
|
||||
<receiver android:name="com.android.launcher3.AppWidgetsRestoredReceiver"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_HOST_RESTORED"/>
|
||||
</intent-filter>
|
||||
|
@ -117,6 +117,7 @@
|
|||
android:name="com.android.launcher3.notification.NotificationListener"
|
||||
android:label="@string/notification_dots_service_title"
|
||||
android:enabled="@bool/notification_dots_enabled"
|
||||
android:exported="true"
|
||||
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
|
||||
<intent-filter>
|
||||
<action android:name="android.service.notification.NotificationListenerService" />
|
||||
|
@ -130,6 +131,7 @@
|
|||
android:theme="@style/AppItemActivityTheme"
|
||||
android:excludeFromRecents="true"
|
||||
android:autoRemoveFromRecents="true"
|
||||
android:exported="true"
|
||||
android:label="@string/action_add_to_workspace" >
|
||||
<intent-filter>
|
||||
<action android:name="android.content.pm.action.CONFIRM_PIN_SHORTCUT" />
|
||||
|
@ -165,6 +167,7 @@
|
|||
android:name="com.android.launcher3.settings.SettingsActivity"
|
||||
android:label="@string/settings_button_text"
|
||||
android:theme="@style/HomeSettingsTheme"
|
||||
android:exported="true"
|
||||
android:autoRemoveFromRecents="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.APPLICATION_PREFERENCES" />
|
||||
|
@ -187,6 +190,7 @@
|
|||
android:name="com.android.launcher3.secondarydisplay.SecondaryDisplayLauncher"
|
||||
android:theme="@style/AppTheme"
|
||||
android:launchMode="singleTop"
|
||||
android:exported="true"
|
||||
android:enabled="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
android:resizeableActivity="true"
|
||||
android:resumeWhilePausing="true"
|
||||
android:taskAffinity=""
|
||||
android:exported="true"
|
||||
android:enabled="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
|
|
@ -164,6 +164,12 @@ public class DebugTestInformationHandler extends TestInformationHandler {
|
|||
}
|
||||
|
||||
case TestProtocol.REQUEST_GET_TEST_EVENTS: {
|
||||
if (sEvents == null) {
|
||||
// sEvents can be null if Launcher died and restarted after
|
||||
// REQUEST_START_EVENT_LOGGING.
|
||||
return response;
|
||||
}
|
||||
|
||||
synchronized (sEvents) {
|
||||
response.putStringArrayList(
|
||||
TestProtocol.TEST_INFO_RESPONSE_FIELD, new ArrayList<>(sEvents));
|
||||
|
|
|
@ -131,6 +131,7 @@ message Application {
|
|||
// Legacy shortcuts and shortcuts handled by ShortcutManager
|
||||
message Shortcut {
|
||||
optional string shortcut_name = 1;
|
||||
optional string shortcut_id = 2;
|
||||
}
|
||||
|
||||
// AppWidgets handled by AppWidgetManager
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
android:resizeableActivity="true"
|
||||
android:resumeWhilePausing="true"
|
||||
android:taskAffinity=""
|
||||
android:exported="true"
|
||||
android:enabled="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
** limitations under the License.
|
||||
*/
|
||||
-->
|
||||
<manifest
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="com.android.launcher3">
|
||||
|
||||
|
@ -32,8 +32,7 @@
|
|||
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
|
||||
<uses-permission android:name="${packageName}.permission.HOTSEAT_EDU" />
|
||||
|
||||
<application
|
||||
android:backupAgent="com.android.launcher3.LauncherBackupAgent"
|
||||
<application android:backupAgent="com.android.launcher3.LauncherBackupAgent"
|
||||
android:fullBackupOnly="true"
|
||||
android:fullBackupContent="@xml/backupscheme"
|
||||
android:hardwareAccelerated="true"
|
||||
|
@ -44,10 +43,10 @@
|
|||
android:restoreAnyVersion="true"
|
||||
android:supportsRtl="true">
|
||||
|
||||
<service
|
||||
android:name="com.android.quickstep.TouchInteractionService"
|
||||
<service android:name="com.android.quickstep.TouchInteractionService"
|
||||
android:permission="android.permission.STATUS_BAR_SERVICE"
|
||||
android:directBootAware="true" >
|
||||
android:directBootAware="true"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.QUICKSTEP_SERVICE"/>
|
||||
</intent-filter>
|
||||
|
@ -66,8 +65,7 @@
|
|||
android:taskAffinity=""/>
|
||||
|
||||
<!-- Content provider to settings search. The autority should be same as the packageName -->
|
||||
<provider
|
||||
android:name="com.android.quickstep.LauncherSearchIndexablesProvider"
|
||||
<provider android:name="com.android.quickstep.LauncherSearchIndexablesProvider"
|
||||
android:authorities="${packageName}"
|
||||
android:grantUriPermissions="true"
|
||||
android:multiprocess="true"
|
||||
|
@ -79,32 +77,28 @@
|
|||
</provider>
|
||||
|
||||
<!-- FileProvider used for sharing images. -->
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
<provider android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="${packageName}.overview.fileprovider"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
<meta-data
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
<meta-data android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/overview_file_provider_paths"/>
|
||||
</provider>
|
||||
|
||||
<service
|
||||
android:name="com.android.launcher3.uioverrides.dynamicui.WallpaperManagerCompatVL$ColorExtractionService"
|
||||
<service android:name="com.android.launcher3.uioverrides.dynamicui.WallpaperManagerCompatVL$ColorExtractionService"
|
||||
tools:node="remove"/>
|
||||
|
||||
<activity
|
||||
android:name="com.android.launcher3.proxy.ProxyActivityStarter"
|
||||
<activity android:name="com.android.launcher3.proxy.ProxyActivityStarter"
|
||||
android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen"
|
||||
android:launchMode="singleTask"
|
||||
android:clearTaskOnLaunch="true"
|
||||
android:exported="false"/>
|
||||
|
||||
<activity
|
||||
android:name="com.android.quickstep.interaction.GestureSandboxActivity"
|
||||
<activity android:name="com.android.quickstep.interaction.GestureSandboxActivity"
|
||||
android:autoRemoveFromRecents="true"
|
||||
android:excludeFromRecents="true"
|
||||
android:screenOrientation="portrait">
|
||||
android:screenOrientation="portrait"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="com.android.quickstep.action.GESTURE_SANDBOX"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
|
@ -116,7 +110,8 @@
|
|||
android:noHistory="true"
|
||||
android:launchMode="singleTask"
|
||||
android:clearTaskOnLaunch="true"
|
||||
android:permission="${packageName}.permission.HOTSEAT_EDU">
|
||||
android:permission="${packageName}.permission.HOTSEAT_EDU"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="com.android.launcher3.action.SHOW_HYBRID_HOTSEAT_EDU"/>
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
|
|
|
@ -16,6 +16,12 @@
|
|||
package com.android.launcher3.appprediction;
|
||||
|
||||
import static com.android.launcher3.InvariantDeviceProfile.CHANGE_FLAG_GRID;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_APP_LAUNCH_TAP;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ITEM_DROPPED_ON_DONT_SUGGEST;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_QUICKSWITCH_LEFT;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_QUICKSWITCH_RIGHT;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_SWIPE_DOWN;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_TAP;
|
||||
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
|
@ -31,29 +37,38 @@ import android.os.Build;
|
|||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.os.Process;
|
||||
import android.os.SystemClock;
|
||||
import android.os.UserHandle;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.AnyThread;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.UiThread;
|
||||
import androidx.annotation.WorkerThread;
|
||||
|
||||
import com.android.launcher3.InvariantDeviceProfile;
|
||||
import com.android.launcher3.appprediction.PredictionUiStateManager.Client;
|
||||
import com.android.launcher3.logger.LauncherAtom;
|
||||
import com.android.launcher3.logger.LauncherAtom.ContainerInfo;
|
||||
import com.android.launcher3.logger.LauncherAtom.FolderContainer;
|
||||
import com.android.launcher3.logger.LauncherAtom.HotseatContainer;
|
||||
import com.android.launcher3.logger.LauncherAtom.WorkspaceContainer;
|
||||
import com.android.launcher3.logging.StatsLogManager.EventEnum;
|
||||
import com.android.launcher3.model.AppLaunchTracker;
|
||||
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
|
||||
import com.android.systemui.plugins.AppLaunchEventsPlugin;
|
||||
import com.android.systemui.plugins.PluginListener;
|
||||
import com.android.launcher3.pm.UserCache;
|
||||
import com.android.quickstep.logging.StatsLogCompatManager;
|
||||
import com.android.quickstep.logging.StatsLogCompatManager.StatsLogConsumer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* Subclass of app tracker which publishes the data to the prediction engine and gets back results.
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.Q)
|
||||
public class PredictionAppTracker extends AppLaunchTracker
|
||||
implements PluginListener<AppLaunchEventsPlugin> {
|
||||
public class PredictionAppTracker extends AppLaunchTracker implements StatsLogConsumer {
|
||||
|
||||
private static final String TAG = "PredictionAppTracker";
|
||||
private static final boolean DBG = false;
|
||||
|
@ -65,11 +80,9 @@ public class PredictionAppTracker extends AppLaunchTracker
|
|||
|
||||
protected final Context mContext;
|
||||
private final Handler mMessageHandler;
|
||||
private final List<AppLaunchEventsPlugin> mAppLaunchEventsPluginsList;
|
||||
|
||||
// Accessed only on worker thread
|
||||
private AppPredictor mHomeAppPredictor;
|
||||
private AppPredictor mRecentsOverviewPredictor;
|
||||
|
||||
public PredictionAppTracker(Context context) {
|
||||
mContext = context;
|
||||
|
@ -77,10 +90,6 @@ public class PredictionAppTracker extends AppLaunchTracker
|
|||
InvariantDeviceProfile.INSTANCE.get(mContext).addOnChangeListener(this::onIdpChanged);
|
||||
|
||||
mMessageHandler.sendEmptyMessage(MSG_INIT);
|
||||
|
||||
mAppLaunchEventsPluginsList = new ArrayList<>();
|
||||
PluginManagerWrapper.INSTANCE.get(context)
|
||||
.addPluginListener(this, AppLaunchEventsPlugin.class, true);
|
||||
}
|
||||
|
||||
@UiThread
|
||||
|
@ -97,10 +106,7 @@ public class PredictionAppTracker extends AppLaunchTracker
|
|||
mHomeAppPredictor.destroy();
|
||||
mHomeAppPredictor = null;
|
||||
}
|
||||
if (mRecentsOverviewPredictor != null) {
|
||||
mRecentsOverviewPredictor.destroy();
|
||||
mRecentsOverviewPredictor = null;
|
||||
}
|
||||
StatsLogCompatManager.LOGS_CONSUMER.remove(this);
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
|
@ -142,7 +148,7 @@ public class PredictionAppTracker extends AppLaunchTracker
|
|||
// Initialize the clients
|
||||
int count = InvariantDeviceProfile.INSTANCE.get(mContext).numAllAppsColumns;
|
||||
mHomeAppPredictor = createPredictor(Client.HOME, count);
|
||||
mRecentsOverviewPredictor = createPredictor(Client.OVERVIEW, count);
|
||||
StatsLogCompatManager.LOGS_CONSUMER.add(this);
|
||||
return true;
|
||||
}
|
||||
case MSG_DESTROY: {
|
||||
|
@ -157,12 +163,7 @@ public class PredictionAppTracker extends AppLaunchTracker
|
|||
}
|
||||
case MSG_PREDICT: {
|
||||
if (mHomeAppPredictor != null) {
|
||||
String client = (String) msg.obj;
|
||||
if (Client.HOME.id.equals(client)) {
|
||||
mHomeAppPredictor.requestPredictionUpdate();
|
||||
} else {
|
||||
mRecentsOverviewPredictor.requestPredictionUpdate();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -179,98 +180,142 @@ public class PredictionAppTracker extends AppLaunchTracker
|
|||
if (DBG) {
|
||||
Log.d(TAG, String.format("Sent immediate message to update %s", client));
|
||||
}
|
||||
|
||||
// Relay onReturnedToHome to every plugin.
|
||||
mAppLaunchEventsPluginsList.forEach(AppLaunchEventsPlugin::onReturnedToHome);
|
||||
}
|
||||
|
||||
@Override
|
||||
@UiThread
|
||||
public void onStartShortcut(String packageName, String shortcutId, UserHandle user,
|
||||
String container) {
|
||||
// TODO: Use the full shortcut info
|
||||
AppTarget target = new AppTarget.Builder(
|
||||
new AppTargetId("shortcut:" + shortcutId), packageName, user)
|
||||
.setClassName(shortcutId)
|
||||
.build();
|
||||
|
||||
sendLaunch(target, container);
|
||||
|
||||
// Relay onStartShortcut info to every connected plugin.
|
||||
mAppLaunchEventsPluginsList
|
||||
.forEach(plugin -> plugin.onStartShortcut(
|
||||
packageName,
|
||||
shortcutId,
|
||||
user,
|
||||
container != null ? container : CONTAINER_DEFAULT)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@UiThread
|
||||
public void onStartApp(ComponentName cn, UserHandle user, String container) {
|
||||
if (cn != null) {
|
||||
AppTarget target = new AppTarget.Builder(
|
||||
new AppTargetId("app:" + cn), cn.getPackageName(), user)
|
||||
.setClassName(cn.getClassName())
|
||||
.build();
|
||||
sendLaunch(target, container);
|
||||
|
||||
// Relay onStartApp to every connected plugin.
|
||||
mAppLaunchEventsPluginsList
|
||||
.forEach(plugin -> plugin.onStartApp(
|
||||
cn,
|
||||
user,
|
||||
container != null ? container : CONTAINER_DEFAULT)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@UiThread
|
||||
public void onDismissApp(ComponentName cn, UserHandle user, String container) {
|
||||
if (cn == null) return;
|
||||
AppTarget target = new AppTarget.Builder(
|
||||
new AppTargetId("app: " + cn), cn.getPackageName(), user)
|
||||
.setClassName(cn.getClassName())
|
||||
.build();
|
||||
sendDismiss(target, container);
|
||||
|
||||
// Relay onDismissApp to every connected plugin.
|
||||
mAppLaunchEventsPluginsList
|
||||
.forEach(plugin -> plugin.onDismissApp(
|
||||
cn,
|
||||
user,
|
||||
container != null ? container : CONTAINER_DEFAULT)
|
||||
);
|
||||
}
|
||||
|
||||
@UiThread
|
||||
private void sendEvent(AppTarget target, String container, int eventId) {
|
||||
@AnyThread
|
||||
private void sendEvent(LauncherAtom.ItemInfo atomInfo, int eventId) {
|
||||
AppTarget target = toAppTarget(atomInfo);
|
||||
if (target != null) {
|
||||
AppTargetEvent event = new AppTargetEvent.Builder(target, eventId)
|
||||
.setLaunchLocation(container == null ? CONTAINER_DEFAULT : container)
|
||||
.setLaunchLocation(getContainer(atomInfo))
|
||||
.build();
|
||||
Message.obtain(mMessageHandler, MSG_LAUNCH, event).sendToTarget();
|
||||
}
|
||||
|
||||
@UiThread
|
||||
private void sendLaunch(AppTarget target, String container) {
|
||||
sendEvent(target, container, AppTargetEvent.ACTION_LAUNCH);
|
||||
}
|
||||
|
||||
@UiThread
|
||||
private void sendDismiss(AppTarget target, String container) {
|
||||
sendEvent(target, container, AppTargetEvent.ACTION_DISMISS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPluginConnected(AppLaunchEventsPlugin appLaunchEventsPlugin, Context context) {
|
||||
mAppLaunchEventsPluginsList.add(appLaunchEventsPlugin);
|
||||
public void consume(EventEnum event, LauncherAtom.ItemInfo atomInfo) {
|
||||
if (event == LAUNCHER_APP_LAUNCH_TAP
|
||||
|| event == LAUNCHER_TASK_LAUNCH_SWIPE_DOWN
|
||||
|| event == LAUNCHER_TASK_LAUNCH_TAP
|
||||
|| event == LAUNCHER_QUICKSWITCH_RIGHT
|
||||
|| event == LAUNCHER_QUICKSWITCH_LEFT) {
|
||||
sendEvent(atomInfo, AppTargetEvent.ACTION_LAUNCH);
|
||||
} else if (event == LAUNCHER_ITEM_DROPPED_ON_DONT_SUGGEST) {
|
||||
sendEvent(atomInfo, AppTargetEvent.ACTION_DISMISS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPluginDisconnected(AppLaunchEventsPlugin appLaunchEventsPlugin) {
|
||||
mAppLaunchEventsPluginsList.remove(appLaunchEventsPlugin);
|
||||
@Nullable
|
||||
private AppTarget toAppTarget(LauncherAtom.ItemInfo info) {
|
||||
UserHandle userHandle = Process.myUserHandle();
|
||||
if (info.getIsWork()) {
|
||||
userHandle = UserCache.INSTANCE.get(mContext).getUserProfiles().stream()
|
||||
.filter(((Predicate<UserHandle>) userHandle::equals).negate())
|
||||
.findAny()
|
||||
.orElse(null);
|
||||
}
|
||||
if (userHandle == null) {
|
||||
return null;
|
||||
}
|
||||
ComponentName cn = null;
|
||||
String id = null;
|
||||
|
||||
switch (info.getItemCase()) {
|
||||
case APPLICATION: {
|
||||
LauncherAtom.Application app = info.getApplication();
|
||||
if ((cn = parseNullable(app.getComponentName())) != null) {
|
||||
id = "app:" + cn.getPackageName();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SHORTCUT: {
|
||||
LauncherAtom.Shortcut si = info.getShortcut();
|
||||
if (!TextUtils.isEmpty(si.getShortcutId())
|
||||
&& (cn = parseNullable(si.getShortcutName())) != null) {
|
||||
id = "shortcut:" + si.getShortcutId();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WIDGET: {
|
||||
LauncherAtom.Widget widget = info.getWidget();
|
||||
if ((cn = parseNullable(widget.getComponentName())) != null) {
|
||||
id = "widget:" + cn.getPackageName();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TASK: {
|
||||
LauncherAtom.Task task = info.getTask();
|
||||
if ((cn = parseNullable(task.getComponentName())) != null) {
|
||||
id = "app:" + cn.getPackageName();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FOLDER_ICON: {
|
||||
id = "folder:" + SystemClock.uptimeMillis();
|
||||
cn = new ComponentName(mContext.getPackageName(), "#folder");
|
||||
}
|
||||
}
|
||||
if (id != null && cn != null) {
|
||||
return new AppTarget.Builder(new AppTargetId(id), cn.getPackageName(), userHandle)
|
||||
.setClassName(cn.getClassName())
|
||||
.build();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String getContainer(LauncherAtom.ItemInfo info) {
|
||||
ContainerInfo ci = info.getContainerInfo();
|
||||
switch (ci.getContainerCase()) {
|
||||
case WORKSPACE: {
|
||||
// In case the item type is not widgets, the spaceX and spanY default to 1.
|
||||
int spanX = info.getWidget().getSpanX();
|
||||
int spanY = info.getWidget().getSpanY();
|
||||
return getWorkspaceContainerString(ci.getWorkspace(), spanX, spanY);
|
||||
}
|
||||
case HOTSEAT: {
|
||||
return getHotseatContainerString(ci.getHotseat());
|
||||
}
|
||||
case TASK_SWITCHER_CONTAINER: {
|
||||
return "task-switcher";
|
||||
}
|
||||
case ALL_APPS_CONTAINER: {
|
||||
return "all-apps";
|
||||
}
|
||||
case SEARCH_RESULT_CONTAINER: {
|
||||
return "search-results";
|
||||
}
|
||||
case PREDICTED_HOTSEAT_CONTAINER: {
|
||||
return "predictions/hotseat";
|
||||
}
|
||||
case PREDICTION_CONTAINER: {
|
||||
return "predictions";
|
||||
}
|
||||
case FOLDER: {
|
||||
FolderContainer fc = ci.getFolder();
|
||||
switch (fc.getParentContainerCase()) {
|
||||
case WORKSPACE:
|
||||
return "folder/" + getWorkspaceContainerString(fc.getWorkspace(), 1, 1);
|
||||
case HOTSEAT:
|
||||
return "folder/" + getHotseatContainerString(fc.getHotseat());
|
||||
}
|
||||
return "folder";
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private static String getWorkspaceContainerString(WorkspaceContainer wc, int spanX, int spanY) {
|
||||
return String.format(Locale.ENGLISH, "workspace/%d/[%d,%d]/[%d,%d]",
|
||||
wc.getPageIndex(), wc.getGridX(), wc.getGridY(), spanX, spanY);
|
||||
}
|
||||
|
||||
private static String getHotseatContainerString(HotseatContainer hc) {
|
||||
return String.format(Locale.ENGLISH, "hotseat/%d", hc.getIndex());
|
||||
}
|
||||
|
||||
private static ComponentName parseNullable(String componentNameString) {
|
||||
return TextUtils.isEmpty(componentNameString)
|
||||
? null : ComponentName.unflattenFromString(componentNameString);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,7 +56,6 @@ 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.AppLaunchTracker;
|
||||
import com.android.launcher3.model.data.AppInfo;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.ItemInfoWithIcon;
|
||||
|
@ -93,9 +92,6 @@ public class PredictionRowView extends LinearLayout implements
|
|||
private static final Interpolator ALPHA_FACTOR_INTERPOLATOR =
|
||||
(t) -> (t < 0.8f) ? 0 : (t - 0.8f) / 0.2f;
|
||||
|
||||
private static final OnClickListener PREDICTION_CLICK_LISTENER =
|
||||
ItemClickHandler.getInstance(AppLaunchTracker.CONTAINER_PREDICTIONS);
|
||||
|
||||
private final Launcher mLauncher;
|
||||
private final PredictionUiStateManager mPredictionUiStateManager;
|
||||
private int mNumPredictedAppsPerRow;
|
||||
|
@ -246,7 +242,7 @@ public class PredictionRowView extends LinearLayout implements
|
|||
while (getChildCount() < mNumPredictedAppsPerRow) {
|
||||
BubbleTextView icon = (BubbleTextView) inflater.inflate(
|
||||
R.layout.all_apps_icon, this, false);
|
||||
icon.setOnClickListener(PREDICTION_CLICK_LISTENER);
|
||||
icon.setOnClickListener(ItemClickHandler.INSTANCE);
|
||||
icon.setOnLongClickListener(ItemLongClickListener.INSTANCE_ALL_APPS);
|
||||
icon.setLongPressTimeoutFactor(1f);
|
||||
icon.setOnFocusChangeListener(mFocusHelper);
|
||||
|
|
|
@ -75,8 +75,7 @@ public class PredictionUiStateManager implements StateListener<LauncherState>,
|
|||
|
||||
// TODO (b/129421797): Update the client constants
|
||||
public enum Client {
|
||||
HOME("home"),
|
||||
OVERVIEW("overview");
|
||||
HOME("home");
|
||||
|
||||
public final String id;
|
||||
|
||||
|
@ -91,10 +90,9 @@ public class PredictionUiStateManager implements StateListener<LauncherState>,
|
|||
private final Context mContext;
|
||||
|
||||
private final DynamicItemCache mDynamicItemCache;
|
||||
private final List[] mPredictionServicePredictions;
|
||||
private List mPredictionServicePredictions = Collections.emptyList();
|
||||
|
||||
private int mMaxIconsPerRow;
|
||||
private Client mActiveClient;
|
||||
|
||||
private AllAppsContainerView mAppsView;
|
||||
|
||||
|
@ -108,16 +106,10 @@ public class PredictionUiStateManager implements StateListener<LauncherState>,
|
|||
|
||||
mDynamicItemCache = new DynamicItemCache(context, this::onAppsUpdated);
|
||||
|
||||
mActiveClient = Client.HOME;
|
||||
|
||||
InvariantDeviceProfile idp = LauncherAppState.getIDP(context);
|
||||
mMaxIconsPerRow = idp.numColumns;
|
||||
|
||||
idp.addOnChangeListener(this);
|
||||
mPredictionServicePredictions = new List[Client.values().length];
|
||||
for (int i = 0; i < mPredictionServicePredictions.length; i++) {
|
||||
mPredictionServicePredictions[i] = Collections.emptyList();
|
||||
}
|
||||
mGettingValidPredictionResults = Utilities.getDevicePrefs(context)
|
||||
.getBoolean(LAST_PREDICTION_ENABLED_STATE, true);
|
||||
|
||||
|
@ -130,18 +122,6 @@ public class PredictionUiStateManager implements StateListener<LauncherState>,
|
|||
mMaxIconsPerRow = profile.numColumns;
|
||||
}
|
||||
|
||||
public Client getClient() {
|
||||
return mActiveClient;
|
||||
}
|
||||
|
||||
public void switchClient(Client client) {
|
||||
if (client == mActiveClient) {
|
||||
return;
|
||||
}
|
||||
mActiveClient = client;
|
||||
dispatchOnChange(true);
|
||||
}
|
||||
|
||||
public void setTargetAppsView(AllAppsContainerView appsView) {
|
||||
if (mAppsView != null) {
|
||||
mAppsView.getAppsStore().removeUpdateListener(this);
|
||||
|
@ -195,10 +175,8 @@ public class PredictionUiStateManager implements StateListener<LauncherState>,
|
|||
}
|
||||
|
||||
private void updatePredictionStateAfterCallback() {
|
||||
boolean validResults = false;
|
||||
for (List l : mPredictionServicePredictions) {
|
||||
validResults |= l != null && !l.isEmpty();
|
||||
}
|
||||
boolean validResults = mPredictionServicePredictions != null
|
||||
&& !mPredictionServicePredictions.isEmpty();
|
||||
if (validResults != mGettingValidPredictionResults) {
|
||||
mGettingValidPredictionResults = validResults;
|
||||
Utilities.getDevicePrefs(mContext).edit()
|
||||
|
@ -210,7 +188,7 @@ public class PredictionUiStateManager implements StateListener<LauncherState>,
|
|||
|
||||
public AppPredictor.Callback appPredictorCallback(Client client) {
|
||||
return targets -> {
|
||||
mPredictionServicePredictions[client.ordinal()] = targets;
|
||||
mPredictionServicePredictions = targets;
|
||||
updatePredictionStateAfterCallback();
|
||||
};
|
||||
}
|
||||
|
@ -238,7 +216,7 @@ public class PredictionUiStateManager implements StateListener<LauncherState>,
|
|||
|
||||
state.apps = new ArrayList<>();
|
||||
|
||||
List<AppTarget> appTargets = mPredictionServicePredictions[mActiveClient.ordinal()];
|
||||
List<AppTarget> appTargets = mPredictionServicePredictions;
|
||||
if (!appTargets.isEmpty()) {
|
||||
for (AppTarget appTarget : appTargets) {
|
||||
ComponentKey key;
|
||||
|
|
|
@ -34,8 +34,6 @@ import android.os.Bundle;
|
|||
import android.util.Log;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.BaseQuickstepLauncher;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.Launcher;
|
||||
|
@ -129,12 +127,11 @@ public class QuickstepLauncher extends BaseQuickstepLauncher {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean startActivitySafely(View v, Intent intent, ItemInfo item,
|
||||
@Nullable String sourceContainer) {
|
||||
public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
|
||||
if (mHotseatPredictionController != null) {
|
||||
mHotseatPredictionController.setPauseUIUpdate(true);
|
||||
}
|
||||
return super.startActivitySafely(v, intent, item, sourceContainer);
|
||||
return super.startActivitySafely(v, intent, item);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -24,6 +24,7 @@ import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MOD
|
|||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.app.ActivityManager.RunningTaskInfo;
|
||||
import android.util.Log;
|
||||
import android.view.animation.Interpolator;
|
||||
|
||||
|
@ -52,17 +53,17 @@ final class AppToOverviewAnimationProvider<T extends StatefulActivity<?>> extend
|
|||
|
||||
private final BaseActivityInterface<?, T> mActivityInterface;
|
||||
// The id of the currently running task that is transitioning to overview.
|
||||
private final int mTargetTaskId;
|
||||
private final RunningTaskInfo mTargetTask;
|
||||
private final RecentsAnimationDeviceState mDeviceState;
|
||||
|
||||
private T mActivity;
|
||||
private RecentsView mRecentsView;
|
||||
|
||||
AppToOverviewAnimationProvider(
|
||||
BaseActivityInterface<?, T> activityInterface, int targetTaskId,
|
||||
BaseActivityInterface<?, T> activityInterface, RunningTaskInfo targetTask,
|
||||
RecentsAnimationDeviceState deviceState) {
|
||||
mActivityInterface = activityInterface;
|
||||
mTargetTaskId = targetTaskId;
|
||||
mTargetTask = targetTask;
|
||||
mDeviceState = deviceState;
|
||||
}
|
||||
|
||||
|
@ -73,7 +74,7 @@ final class AppToOverviewAnimationProvider<T extends StatefulActivity<?>> extend
|
|||
* @param wasVisible true if it was visible before
|
||||
*/
|
||||
boolean onActivityReady(T activity, Boolean wasVisible) {
|
||||
activity.<RecentsView>getOverviewPanel().showCurrentTask(mTargetTaskId);
|
||||
activity.<RecentsView>getOverviewPanel().showCurrentTask(mTargetTask);
|
||||
AbstractFloatingView.closeAllOpenViews(activity, wasVisible);
|
||||
BaseActivityInterface.AnimationFactory factory = mActivityInterface.prepareRecentsUI(
|
||||
mDeviceState,
|
||||
|
@ -122,7 +123,8 @@ final class AppToOverviewAnimationProvider<T extends StatefulActivity<?>> extend
|
|||
wallpaperTargets, MODE_CLOSING);
|
||||
|
||||
// Use the top closing app to determine the insets for the animation
|
||||
RemoteAnimationTargetCompat runningTaskTarget = targets.findTask(mTargetTaskId);
|
||||
RemoteAnimationTargetCompat runningTaskTarget = mTargetTask == null ? null
|
||||
: targets.findTask(mTargetTask.taskId);
|
||||
if (runningTaskTarget == null) {
|
||||
Log.e(TAG, "No closing app");
|
||||
return pa.buildAnim();
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
*/
|
||||
package com.android.quickstep;
|
||||
|
||||
import static android.widget.Toast.LENGTH_SHORT;
|
||||
|
||||
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
|
||||
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
|
||||
import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC;
|
||||
|
@ -27,11 +29,13 @@ import android.graphics.Rect;
|
|||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.CallSuper;
|
||||
import androidx.annotation.UiThread;
|
||||
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.statemanager.StatefulActivity;
|
||||
import com.android.launcher3.testing.TestProtocol;
|
||||
import com.android.launcher3.util.VibratorWrapper;
|
||||
|
@ -138,10 +142,10 @@ public abstract class BaseSwipeUpHandler<T extends StatefulActivity<?>, Q extend
|
|||
mRecentsView.getNextPageTaskView().launchTask(false /* animate */,
|
||||
true /* freezeTaskList */);
|
||||
} else {
|
||||
int taskId = mRecentsView.getNextPageTaskView().getTask().key.id;
|
||||
if (!mCanceled) {
|
||||
TaskView nextTask = mRecentsView.getTaskView(taskId);
|
||||
TaskView nextTask = mRecentsView.getNextPageTaskView();
|
||||
if (nextTask != null) {
|
||||
int taskId = nextTask.getTask().key.id;
|
||||
mGestureState.updateLastStartedTaskId(taskId);
|
||||
boolean hasTaskPreviouslyAppeared = mGestureState.getPreviouslyAppearedTaskIds()
|
||||
.contains(taskId);
|
||||
|
@ -158,6 +162,10 @@ public abstract class BaseSwipeUpHandler<T extends StatefulActivity<?>, Q extend
|
|||
mRecentsAnimationController.finish(true /* toRecents */, null);
|
||||
}
|
||||
}, MAIN_EXECUTOR.getHandler());
|
||||
} else {
|
||||
mActivityInterface.onLaunchTaskFailed();
|
||||
Toast.makeText(mContext, R.string.activity_not_available, LENGTH_SHORT).show();
|
||||
mRecentsAnimationController.finish(true /* toRecents */, null);
|
||||
}
|
||||
}
|
||||
mCanceled = false;
|
||||
|
|
|
@ -38,7 +38,6 @@ import static com.android.quickstep.GestureState.STATE_END_TARGET_ANIMATION_FINI
|
|||
import static com.android.quickstep.GestureState.STATE_END_TARGET_SET;
|
||||
import static com.android.quickstep.GestureState.STATE_RECENTS_SCROLLING_FINISHED;
|
||||
import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
|
||||
import static com.android.quickstep.SysUINavigationMode.Mode.TWO_BUTTONS;
|
||||
import static com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState.HIDE;
|
||||
import static com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState.PEEK;
|
||||
import static com.android.quickstep.views.RecentsView.UPDATE_SYSUI_FLAGS_THRESHOLD;
|
||||
|
@ -60,6 +59,7 @@ import android.view.ViewTreeObserver.OnDrawListener;
|
|||
import android.view.WindowInsets;
|
||||
import android.view.animation.Interpolator;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.UiThread;
|
||||
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
|
@ -70,6 +70,7 @@ import com.android.launcher3.anim.AnimationSuccessListener;
|
|||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||
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.userevent.nano.LauncherLogProto.Action.Direction;
|
||||
|
@ -266,10 +267,6 @@ public abstract class BaseSwipeUpHandlerV2<T extends StatefulActivity<?>, Q exte
|
|||
mStateCallback.runOnceAtState(STATE_HANDLER_INVALIDATED | STATE_RESUME_LAST_TASK,
|
||||
this::notifyTransitionCancelled);
|
||||
|
||||
mGestureState.runOnceAtState(STATE_END_TARGET_SET,
|
||||
() -> mDeviceState.onEndTargetCalculated(mGestureState.getEndTarget(),
|
||||
mActivityInterface));
|
||||
|
||||
if (!ENABLE_QUICKSTEP_LIVE_TILE.get()) {
|
||||
mStateCallback.addChangeListener(STATE_APP_CONTROLLER_RECEIVED | STATE_LAUNCHER_PRESENT
|
||||
| STATE_SCREENSHOT_VIEW_SHOWN | STATE_CAPTURE_SCREENSHOT,
|
||||
|
@ -313,12 +310,6 @@ public abstract class BaseSwipeUpHandlerV2<T extends StatefulActivity<?>, Q exte
|
|||
}
|
||||
|
||||
setupRecentsViewUi();
|
||||
|
||||
if (mDeviceState.getNavMode() == TWO_BUTTONS) {
|
||||
// If the device is in two button mode, swiping up will show overview with predictions
|
||||
// so we need to kick off switching to the overview predictions as soon as possible
|
||||
mActivityInterface.updateOverviewPredictionState();
|
||||
}
|
||||
linkRecentsViewScroll();
|
||||
|
||||
return true;
|
||||
|
@ -400,6 +391,11 @@ public abstract class BaseSwipeUpHandlerV2<T extends StatefulActivity<?>, Q exte
|
|||
mGestureState.getActivityInterface().setOnDeferredActivityLaunchCallback(
|
||||
mOnDeferredActivityLaunch);
|
||||
|
||||
mGestureState.runOnceAtState(STATE_END_TARGET_SET,
|
||||
() -> mDeviceState.getRotationTouchHelper().
|
||||
onEndTargetCalculated(mGestureState.getEndTarget(),
|
||||
mActivityInterface));
|
||||
|
||||
notifyGestureStartedAsync();
|
||||
}
|
||||
|
||||
|
@ -423,7 +419,7 @@ public abstract class BaseSwipeUpHandlerV2<T extends StatefulActivity<?>, Q exte
|
|||
}
|
||||
|
||||
protected void notifyGestureAnimationStartToRecents() {
|
||||
mRecentsView.onGestureAnimationStart(mGestureState.getRunningTaskId());
|
||||
mRecentsView.onGestureAnimationStart(mGestureState.getRunningTask());
|
||||
}
|
||||
|
||||
private void launcherFrameDrawn() {
|
||||
|
@ -451,12 +447,6 @@ public abstract class BaseSwipeUpHandlerV2<T extends StatefulActivity<?>, Q exte
|
|||
@Override
|
||||
public void onMotionPauseChanged(boolean isPaused) {
|
||||
setShelfState(isPaused ? PEEK : HIDE, ShelfPeekAnim.INTERPOLATOR, ShelfPeekAnim.DURATION);
|
||||
|
||||
if (mDeviceState.isFullyGesturalNavMode() && isPaused) {
|
||||
// In fully gestural nav mode, switch to overview predictions once the user has paused
|
||||
// (this is a no-op if the predictions are already in that state)
|
||||
mActivityInterface.updateOverviewPredictionState();
|
||||
}
|
||||
}
|
||||
|
||||
public void maybeUpdateRecentsAttachedState() {
|
||||
|
@ -555,14 +545,6 @@ public abstract class BaseSwipeUpHandlerV2<T extends StatefulActivity<?>, Q exte
|
|||
|
||||
@Override
|
||||
public void updateFinalShift() {
|
||||
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
|
||||
if (mRecentsAnimationTargets != null) {
|
||||
LiveTileOverlay.INSTANCE.update(
|
||||
mTaskViewSimulator.getCurrentCropRect(),
|
||||
mTaskViewSimulator.getCurrentCornerRadius());
|
||||
}
|
||||
}
|
||||
|
||||
final boolean passed = mCurrentShift.value >= MIN_PROGRESS_FOR_OVERVIEW;
|
||||
if (passed != mPassedOverviewThreshold) {
|
||||
mPassedOverviewThreshold = passed;
|
||||
|
@ -573,6 +555,14 @@ public abstract class BaseSwipeUpHandlerV2<T extends StatefulActivity<?>, Q exte
|
|||
|
||||
updateSysUiFlags(mCurrentShift.value);
|
||||
applyWindowTransform();
|
||||
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
|
||||
if (mRecentsAnimationTargets != null) {
|
||||
LiveTileOverlay.INSTANCE.update(
|
||||
mTaskViewSimulator.getCurrentRect(),
|
||||
mTaskViewSimulator.getCurrentCornerRadius());
|
||||
}
|
||||
}
|
||||
|
||||
updateLauncherTransitionProgress();
|
||||
}
|
||||
|
||||
|
@ -889,22 +879,7 @@ public abstract class BaseSwipeUpHandlerV2<T extends StatefulActivity<?>, Q exte
|
|||
animateToProgress(startShift, endShift, duration, interpolator, endTarget, velocityPxPerMs);
|
||||
}
|
||||
|
||||
private void doLogGesture(GestureEndTarget endTarget) {
|
||||
DeviceProfile dp = mDp;
|
||||
if (dp == null || mDownPos == null) {
|
||||
// We probably never received an animation controller, skip logging.
|
||||
return;
|
||||
}
|
||||
|
||||
int pageIndex = endTarget == LAST_TASK
|
||||
? LOG_NO_OP_PAGE_INDEX
|
||||
: mRecentsView.getNextPage();
|
||||
UserEventDispatcher.newInstance(mContext).logStateChangeAction(
|
||||
mLogAction, mLogDirection,
|
||||
(int) mDownPos.x, (int) mDownPos.y,
|
||||
ContainerType.NAVBAR, ContainerType.APP,
|
||||
endTarget.containerType,
|
||||
pageIndex);
|
||||
private void doLogGesture(GestureEndTarget endTarget, @Nullable TaskView targetTask) {
|
||||
StatsLogManager.EventEnum event;
|
||||
switch (endTarget) {
|
||||
case HOME:
|
||||
|
@ -922,10 +897,29 @@ public abstract class BaseSwipeUpHandlerV2<T extends StatefulActivity<?>, Q exte
|
|||
default:
|
||||
event = IGNORE;
|
||||
}
|
||||
StatsLogManager.newInstance(mContext).logger()
|
||||
StatsLogger logger = StatsLogManager.newInstance(mContext).logger()
|
||||
.withSrcState(LAUNCHER_STATE_BACKGROUND)
|
||||
.withDstState(StatsLogManager.containerTypeToAtomState(endTarget.containerType))
|
||||
.log(event);
|
||||
.withDstState(StatsLogManager.containerTypeToAtomState(endTarget.containerType));
|
||||
if (targetTask != null) {
|
||||
logger.withItemInfo(targetTask.getItemInfo());
|
||||
}
|
||||
logger.log(event);
|
||||
|
||||
|
||||
DeviceProfile dp = mDp;
|
||||
if (dp == null || mDownPos == null) {
|
||||
// We probably never received an animation controller, skip logging.
|
||||
return;
|
||||
}
|
||||
int pageIndex = endTarget == LAST_TASK
|
||||
? LOG_NO_OP_PAGE_INDEX
|
||||
: mRecentsView.getNextPage();
|
||||
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. */
|
||||
|
@ -1130,7 +1124,7 @@ public abstract class BaseSwipeUpHandlerV2<T extends StatefulActivity<?>, Q exte
|
|||
private void resumeLastTask() {
|
||||
mRecentsAnimationController.finish(false /* toRecents */, null);
|
||||
ActiveGestureLog.INSTANCE.addLog("finishRecentsAnimation", false);
|
||||
doLogGesture(LAST_TASK);
|
||||
doLogGesture(LAST_TASK, null);
|
||||
reset();
|
||||
}
|
||||
|
||||
|
@ -1145,6 +1139,7 @@ public abstract class BaseSwipeUpHandlerV2<T extends StatefulActivity<?>, Q exte
|
|||
|
||||
@UiThread
|
||||
private void startNewTaskInternal() {
|
||||
TaskView taskToLaunch = mRecentsView == null ? null : mRecentsView.getNextPageTaskView();
|
||||
startNewTask(success -> {
|
||||
if (!success) {
|
||||
reset();
|
||||
|
@ -1153,7 +1148,7 @@ public abstract class BaseSwipeUpHandlerV2<T extends StatefulActivity<?>, Q exte
|
|||
endLauncherTransitionController();
|
||||
updateSysUiFlags(1 /* windowProgress == overview */);
|
||||
}
|
||||
doLogGesture(NEW_TASK);
|
||||
doLogGesture(NEW_TASK, taskToLaunch);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1298,7 +1293,7 @@ public abstract class BaseSwipeUpHandlerV2<T extends StatefulActivity<?>, Q exte
|
|||
() -> mStateCallback.setStateOnUiThread(STATE_CURRENT_TASK_FINISHED));
|
||||
}
|
||||
ActiveGestureLog.INSTANCE.addLog("finishRecentsAnimation", true);
|
||||
doLogGesture(HOME);
|
||||
doLogGesture(HOME, mRecentsView == null ? null : mRecentsView.getCurrentPageTaskView());
|
||||
}
|
||||
|
||||
protected abstract void finishRecentsControllerToHome(Runnable callback);
|
||||
|
@ -1313,7 +1308,7 @@ public abstract class BaseSwipeUpHandlerV2<T extends StatefulActivity<?>, Q exte
|
|||
mRecentsView.onSwipeUpAnimationSuccess();
|
||||
|
||||
SystemUiProxy.INSTANCE.get(mContext).onOverviewShown(false, TAG);
|
||||
doLogGesture(RECENTS);
|
||||
doLogGesture(RECENTS, mRecentsView.getCurrentPageTaskView());
|
||||
reset();
|
||||
}
|
||||
|
||||
|
|
|
@ -140,7 +140,7 @@ public final class FallbackActivityInterface extends
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onExitOverview(RecentsAnimationDeviceState deviceState, Runnable exitRunnable) {
|
||||
public void onExitOverview(RotationTouchHelper deviceState, Runnable exitRunnable) {
|
||||
// no-op, fake landscape not supported for 3P
|
||||
}
|
||||
|
||||
|
|
|
@ -140,7 +140,6 @@ public class FallbackSwipeHandler extends
|
|||
|
||||
private final long mDuration;
|
||||
FallbackHomeAnimationFactory(long duration) {
|
||||
super(null);
|
||||
mDuration = duration;
|
||||
|
||||
if (mRunningOverHome) {
|
||||
|
|
|
@ -105,7 +105,7 @@ public final class LauncherActivityInterface extends
|
|||
// recents, we assume the first task is invisible, making translation off by one task.
|
||||
launcher.getStateManager().reapplyState();
|
||||
launcher.getRootView().setForceHideBackArrow(false);
|
||||
notifyRecentsOfOrientation(deviceState);
|
||||
notifyRecentsOfOrientation(deviceState.getRotationTouchHelper());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -120,7 +120,7 @@ public final class LauncherActivityInterface extends
|
|||
@Override
|
||||
public AnimationFactory prepareRecentsUI(RecentsAnimationDeviceState deviceState,
|
||||
boolean activityVisible, Consumer<AnimatorPlaybackController> callback) {
|
||||
notifyRecentsOfOrientation(deviceState);
|
||||
notifyRecentsOfOrientation(deviceState.getRotationTouchHelper());
|
||||
DefaultAnimationFactory factory = new DefaultAnimationFactory(callback) {
|
||||
@Override
|
||||
public void setShelfState(ShelfAnimState shelfState, Interpolator interpolator,
|
||||
|
@ -228,7 +228,7 @@ public final class LauncherActivityInterface extends
|
|||
|
||||
|
||||
@Override
|
||||
public void onExitOverview(RecentsAnimationDeviceState deviceState, Runnable exitRunnable) {
|
||||
public void onExitOverview(RotationTouchHelper deviceState, Runnable exitRunnable) {
|
||||
final StateManager<LauncherState> stateManager = getCreatedActivity().getStateManager();
|
||||
stateManager.addStateListener(
|
||||
new StateManager.StateListener<LauncherState>() {
|
||||
|
@ -244,11 +244,11 @@ public final class LauncherActivityInterface extends
|
|||
});
|
||||
}
|
||||
|
||||
private void notifyRecentsOfOrientation(RecentsAnimationDeviceState deviceState) {
|
||||
private void notifyRecentsOfOrientation(RotationTouchHelper rotationTouchHelper) {
|
||||
// reset layout on swipe to home
|
||||
RecentsView recentsView = getCreatedActivity().getOverviewPanel();
|
||||
recentsView.setLayoutRotation(deviceState.getCurrentActiveRotation(),
|
||||
deviceState.getDisplayRotation());
|
||||
recentsView.setLayoutRotation(rotationTouchHelper.getCurrentActiveRotation(),
|
||||
rotationTouchHelper.getDisplayRotation());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -261,16 +261,6 @@ public final class LauncherActivityInterface extends
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateOverviewPredictionState() {
|
||||
Launcher launcher = getCreatedActivity();
|
||||
if (launcher == null) {
|
||||
return;
|
||||
}
|
||||
PredictionUiStateManager.INSTANCE.get(launcher).switchClient(
|
||||
PredictionUiStateManager.Client.OVERVIEW);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getContainerType() {
|
||||
final Launcher launcher = getVisibleLauncher();
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
package com.android.quickstep;
|
||||
|
||||
import static com.android.launcher3.LauncherState.NORMAL;
|
||||
import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATION;
|
||||
|
||||
import android.animation.AnimatorSet;
|
||||
import android.content.Context;
|
||||
|
@ -28,6 +29,7 @@ import androidx.annotation.NonNull;
|
|||
import com.android.launcher3.BaseQuickstepLauncher;
|
||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||
import com.android.launcher3.views.FloatingIconView;
|
||||
import com.android.quickstep.util.RectFSpringAnim;
|
||||
import com.android.quickstep.util.StaggeredWorkspaceAnim;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.quickstep.views.TaskView;
|
||||
|
@ -72,36 +74,39 @@ public class LauncherSwipeHandlerV2 extends
|
|||
mActivity.getRootView().setForceHideBackArrow(true);
|
||||
mActivity.setHintUserWillBeActive();
|
||||
|
||||
homeAnimFactory = new HomeAnimationFactory(floatingIconView) {
|
||||
|
||||
if (canUseWorkspaceView) {
|
||||
// We want the window alpha to be 0 once this threshold is met, so that the
|
||||
// FolderIconView can be seen morphing into the icon shape.
|
||||
float windowAlphaThreshold = 1f - SHAPE_PROGRESS_DURATION;
|
||||
homeAnimFactory = new LauncherHomeAnimationFactory() {
|
||||
@Override
|
||||
public RectF getWindowTargetRect() {
|
||||
if (canUseWorkspaceView) {
|
||||
return iconLocation;
|
||||
} else {
|
||||
return super.getWindowTargetRect();
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public AnimatorPlaybackController createActivityAnimationToHome() {
|
||||
// Return an empty APC here since we have an non-user controlled animation
|
||||
// to home.
|
||||
long accuracy = 2 * Math.max(mDp.widthPx, mDp.heightPx);
|
||||
return mActivity.getStateManager().createAnimationToNewWorkspace(
|
||||
NORMAL, accuracy, 0 /* animComponents */);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playAtomicAnimation(float velocity) {
|
||||
new StaggeredWorkspaceAnim(mActivity, velocity,
|
||||
true /* animateOverviewScrim */).start();
|
||||
public void setAnimation(RectFSpringAnim anim) {
|
||||
anim.addAnimatorListener(floatingIconView);
|
||||
floatingIconView.setOnTargetChangeListener(anim::onTargetPositionChanged);
|
||||
floatingIconView.setFastFinishRunnable(anim::end);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(RectF currentRect, float progress, float radius) {
|
||||
floatingIconView.update(currentRect, 1f, progress, windowAlphaThreshold,
|
||||
radius, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel() {
|
||||
floatingIconView.fastFinish();
|
||||
}
|
||||
};
|
||||
|
||||
} else {
|
||||
homeAnimFactory = new HomeAnimationFactory(null) {
|
||||
homeAnimFactory = new LauncherHomeAnimationFactory();
|
||||
}
|
||||
} else {
|
||||
homeAnimFactory = new HomeAnimationFactory() {
|
||||
@Override
|
||||
public AnimatorPlaybackController createActivityAnimationToHome() {
|
||||
return AnimatorPlaybackController.wrap(new AnimatorSet(), duration);
|
||||
|
@ -118,4 +123,22 @@ public class LauncherSwipeHandlerV2 extends
|
|||
mRecentsAnimationController.finish(
|
||||
true /* toRecents */, callback, true /* sendUserLeaveHint */);
|
||||
}
|
||||
|
||||
private class LauncherHomeAnimationFactory extends HomeAnimationFactory {
|
||||
@NonNull
|
||||
@Override
|
||||
public AnimatorPlaybackController createActivityAnimationToHome() {
|
||||
// Return an empty APC here since we have an non-user controlled animation
|
||||
// to home.
|
||||
long accuracy = 2 * Math.max(mDp.widthPx, mDp.heightPx);
|
||||
return mActivity.getStateManager().createAnimationToNewWorkspace(
|
||||
NORMAL, accuracy, 0 /* animComponents */);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playAtomicAnimation(float velocity) {
|
||||
new StaggeredWorkspaceAnim(mActivity, velocity,
|
||||
true /* animateOverviewScrim */).start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@ import android.view.ViewConfiguration;
|
|||
|
||||
import androidx.annotation.BinderThread;
|
||||
|
||||
import com.android.launcher3.appprediction.PredictionUiStateManager;
|
||||
import com.android.launcher3.logging.UserEventDispatcher;
|
||||
import com.android.launcher3.statemanager.StatefulActivity;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||
|
@ -165,7 +164,7 @@ public class OverviewCommandHelper {
|
|||
mActivityInterface = mOverviewComponentObserver.getActivityInterface();
|
||||
mCreateTime = SystemClock.elapsedRealtime();
|
||||
mAnimationProvider = new AppToOverviewAnimationProvider<>(mActivityInterface,
|
||||
RecentsModel.getRunningTaskId(), mDeviceState);
|
||||
ActivityManagerWrapper.getInstance().getRunningTask(), mDeviceState);
|
||||
|
||||
// Preload the plan
|
||||
mRecentsModel.getTasks(null);
|
||||
|
@ -227,10 +226,6 @@ public class OverviewCommandHelper {
|
|||
LauncherLogProto.ContainerType.TASKSWITCHER);
|
||||
mUserEventLogged = true;
|
||||
}
|
||||
|
||||
// Switch prediction client to overview
|
||||
PredictionUiStateManager.INSTANCE.get(activity).switchClient(
|
||||
PredictionUiStateManager.Client.OVERVIEW);
|
||||
return mAnimationProvider.onActivityReady(activity, wasVisible);
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,6 @@ package com.android.quickstep;
|
|||
|
||||
import static com.android.launcher3.anim.Interpolators.ACCEL_1_5;
|
||||
import static com.android.launcher3.anim.Interpolators.DEACCEL;
|
||||
import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATION;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.content.Context;
|
||||
|
@ -28,7 +27,6 @@ import android.graphics.RectF;
|
|||
import android.view.animation.Interpolator;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.UiThread;
|
||||
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
|
@ -37,7 +35,6 @@ import com.android.launcher3.anim.AnimationSuccessListener;
|
|||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||
import com.android.launcher3.anim.PendingAnimation;
|
||||
import com.android.launcher3.touch.PagedOrientationHandler;
|
||||
import com.android.launcher3.views.FloatingIconView;
|
||||
import com.android.quickstep.util.RectFSpringAnim;
|
||||
import com.android.quickstep.util.TaskViewSimulator;
|
||||
import com.android.quickstep.util.TransformParams;
|
||||
|
@ -85,7 +82,8 @@ public abstract class SwipeUpAnimationLogic {
|
|||
mTransformParams = transformParams;
|
||||
|
||||
mTaskViewSimulator.setLayoutRotation(
|
||||
mDeviceState.getCurrentActiveRotation(), mDeviceState.getDisplayRotation());
|
||||
mDeviceState.getRotationTouchHelper().getCurrentActiveRotation(),
|
||||
mDeviceState.getRotationTouchHelper().getDisplayRotation());
|
||||
}
|
||||
|
||||
protected void initTransitionEndpoints(DeviceProfile dp) {
|
||||
|
@ -148,12 +146,6 @@ public abstract class SwipeUpAnimationLogic {
|
|||
|
||||
protected abstract class HomeAnimationFactory {
|
||||
|
||||
public FloatingIconView mIconView;
|
||||
|
||||
public HomeAnimationFactory(@Nullable FloatingIconView iconView) {
|
||||
mIconView = iconView;
|
||||
}
|
||||
|
||||
public @NonNull RectF getWindowTargetRect() {
|
||||
PagedOrientationHandler orientationHandler = getOrientationHandler();
|
||||
DeviceProfile dp = mDp;
|
||||
|
@ -174,6 +166,12 @@ public abstract class SwipeUpAnimationLogic {
|
|||
public void playAtomicAnimation(float velocity) {
|
||||
// No-op
|
||||
}
|
||||
|
||||
public void setAnimation(RectFSpringAnim anim) { }
|
||||
|
||||
public void update(RectF currentRect, float progress, float radius) { }
|
||||
|
||||
public void onCancel() { }
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -184,8 +182,6 @@ public abstract class SwipeUpAnimationLogic {
|
|||
protected RectFSpringAnim createWindowAnimationToHome(float startProgress,
|
||||
HomeAnimationFactory homeAnimationFactory) {
|
||||
final RectF targetRect = homeAnimationFactory.getWindowTargetRect();
|
||||
final FloatingIconView fiv = homeAnimationFactory.mIconView;
|
||||
final boolean isFloatingIconView = fiv != null;
|
||||
|
||||
mWindowTransitionController.setPlayFraction(startProgress / mDragLengthFactor);
|
||||
mTaskViewSimulator.apply(mTransformParams.setProgress(startProgress));
|
||||
|
@ -203,11 +199,7 @@ public abstract class SwipeUpAnimationLogic {
|
|||
windowToHomePositionMap.mapRect(startRect);
|
||||
|
||||
RectFSpringAnim anim = new RectFSpringAnim(startRect, targetRect, mContext);
|
||||
if (isFloatingIconView) {
|
||||
anim.addAnimatorListener(fiv);
|
||||
fiv.setOnTargetChangeListener(anim::onTargetPositionChanged);
|
||||
fiv.setFastFinishRunnable(anim::end);
|
||||
}
|
||||
homeAnimationFactory.setAnimation(anim);
|
||||
|
||||
SpringAnimationRunner runner = new SpringAnimationRunner(
|
||||
homeAnimationFactory, cropRectF, homeToWindowPositionMap);
|
||||
|
@ -242,32 +234,27 @@ public abstract class SwipeUpAnimationLogic {
|
|||
|
||||
final RectF mWindowCurrentRect = new RectF();
|
||||
final Matrix mHomeToWindowPositionMap;
|
||||
final HomeAnimationFactory mAnimationFactory;
|
||||
|
||||
final FloatingIconView mFIV;
|
||||
final AnimatorPlaybackController mHomeAnim;
|
||||
final RectF mCropRectF;
|
||||
|
||||
final float mStartRadius;
|
||||
final float mEndRadius;
|
||||
final float mWindowAlphaThreshold;
|
||||
|
||||
SpringAnimationRunner(HomeAnimationFactory factory, RectF cropRectF,
|
||||
Matrix homeToWindowPositionMap) {
|
||||
mAnimationFactory = factory;
|
||||
mHomeAnim = factory.createActivityAnimationToHome();
|
||||
mCropRectF = cropRectF;
|
||||
mHomeToWindowPositionMap = homeToWindowPositionMap;
|
||||
|
||||
cropRectF.roundOut(mCropRect);
|
||||
mFIV = factory.mIconView;
|
||||
|
||||
// End on a "round-enough" radius so that the shape reveal doesn't have to do too much
|
||||
// rounding at the end of the animation.
|
||||
mStartRadius = mTaskViewSimulator.getCurrentCornerRadius();
|
||||
mEndRadius = cropRectF.width() / 2f;
|
||||
|
||||
// We want the window alpha to be 0 once this threshold is met, so that the
|
||||
// FolderIconView can be seen morphing into the icon shape.
|
||||
mWindowAlphaThreshold = mFIV != null ? 1f - SHAPE_PROGRESS_DURATION : 1f;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -282,10 +269,7 @@ public abstract class SwipeUpAnimationLogic {
|
|||
.setCornerRadius(cornerRadius);
|
||||
|
||||
mTransformParams.applySurfaceParams(mTransformParams.createSurfaceParams(this));
|
||||
if (mFIV != null) {
|
||||
mFIV.update(currentRect, 1f, progress,
|
||||
mWindowAlphaThreshold, mMatrix.mapRadius(cornerRadius), false);
|
||||
}
|
||||
mAnimationFactory.update(currentRect, progress, mMatrix.mapRadius(cornerRadius));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -298,9 +282,7 @@ public abstract class SwipeUpAnimationLogic {
|
|||
|
||||
@Override
|
||||
public void onCancel() {
|
||||
if (mFIV != null) {
|
||||
mFIV.fastFinish();
|
||||
}
|
||||
mAnimationFactory.onCancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -19,6 +19,7 @@ package com.android.quickstep;
|
|||
import static android.view.Surface.ROTATION_0;
|
||||
|
||||
import static com.android.launcher3.util.MainThreadInitializedObject.forOverride;
|
||||
import static com.android.quickstep.views.OverviewActionsView.DISABLED_NO_THUMBNAIL;
|
||||
import static com.android.quickstep.views.OverviewActionsView.DISABLED_ROTATED;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
|
@ -146,9 +147,11 @@ public class TaskOverlayFactory implements ResourceBasedOverride {
|
|||
*/
|
||||
public void initOverlay(Task task, ThumbnailData thumbnail, Matrix matrix,
|
||||
boolean rotated) {
|
||||
final boolean isAllowedByPolicy = thumbnail.isRealSnapshot;
|
||||
getActionsView().updateDisabledFlags(DISABLED_NO_THUMBNAIL, thumbnail == null);
|
||||
|
||||
if (thumbnail != null) {
|
||||
getActionsView().updateDisabledFlags(DISABLED_ROTATED, rotated);
|
||||
final boolean isAllowedByPolicy = thumbnail.isRealSnapshot;
|
||||
|
||||
getActionsView().setCallbacks(new OverlayUICallbacks() {
|
||||
@Override
|
||||
|
@ -167,6 +170,7 @@ public class TaskOverlayFactory implements ResourceBasedOverride {
|
|||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to save screenshot of the task thumbnail.
|
||||
|
|
|
@ -61,7 +61,6 @@ import com.android.launcher3.R;
|
|||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.logging.UserEventDispatcher;
|
||||
import com.android.launcher3.model.AppLaunchTracker;
|
||||
import com.android.launcher3.provider.RestoreDbTask;
|
||||
import com.android.launcher3.statemanager.StatefulActivity;
|
||||
import com.android.launcher3.testing.TestLogging;
|
||||
|
@ -258,6 +257,7 @@ public class TouchInteractionService extends Service implements PluginListener<O
|
|||
|
||||
private static boolean sConnected = false;
|
||||
private static boolean sIsInitialized = false;
|
||||
private RotationTouchHelper mRotationTouchHelper;
|
||||
|
||||
public static boolean isConnected() {
|
||||
return sConnected;
|
||||
|
@ -298,6 +298,7 @@ public class TouchInteractionService extends Service implements PluginListener<O
|
|||
mDeviceState = new RecentsAnimationDeviceState(this);
|
||||
mDeviceState.addNavigationModeChangedCallback(this::onNavigationModeChanged);
|
||||
mDeviceState.runOnUserUnlocked(this::onUserUnlocked);
|
||||
mRotationTouchHelper = mDeviceState.getRotationTouchHelper();
|
||||
ProtoTracer.INSTANCE.get(this).add(this);
|
||||
|
||||
sConnected = true;
|
||||
|
@ -326,7 +327,7 @@ public class TouchInteractionService extends Service implements PluginListener<O
|
|||
mInputEventReceiver = mInputMonitorCompat.getInputReceiver(Looper.getMainLooper(),
|
||||
mMainChoreographer, this::onInputEvent);
|
||||
|
||||
mDeviceState.updateGestureTouchRegions();
|
||||
mRotationTouchHelper.updateGestureTouchRegions();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -470,9 +471,9 @@ public class TouchInteractionService extends Service implements PluginListener<O
|
|||
if (TestProtocol.sDebugTracing) {
|
||||
Log.d(TestProtocol.NO_SWIPE_TO_HOME, "TouchInteractionService.onInputEvent:DOWN");
|
||||
}
|
||||
mDeviceState.setOrientationTransformIfNeeded(event);
|
||||
mRotationTouchHelper.setOrientationTransformIfNeeded(event);
|
||||
|
||||
if (mDeviceState.isInSwipeUpTouchRegion(event)) {
|
||||
if (mRotationTouchHelper.isInSwipeUpTouchRegion(event)) {
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
Log.d(TestProtocol.NO_SWIPE_TO_HOME,
|
||||
"TouchInteractionService.onInputEvent:isInSwipeUpTouchRegion");
|
||||
|
@ -509,7 +510,7 @@ public class TouchInteractionService extends Service implements PluginListener<O
|
|||
// Other events
|
||||
if (mUncheckedConsumer != InputConsumer.NO_OP) {
|
||||
// Only transform the event if we are handling it in a proper consumer
|
||||
mDeviceState.setOrientationTransformIfNeeded(event);
|
||||
mRotationTouchHelper.setOrientationTransformIfNeeded(event);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -547,7 +548,7 @@ public class TouchInteractionService extends Service implements PluginListener<O
|
|||
gestureState.updatePreviouslyAppearedTaskIds(
|
||||
previousGestureState.getPreviouslyAppearedTaskIds());
|
||||
} else {
|
||||
gestureState.updateRunningTask(TraceHelper.whitelistIpcs("getRunningTask.0",
|
||||
gestureState.updateRunningTask(TraceHelper.allowIpcs("getRunningTask.0",
|
||||
() -> mAM.getRunningTask(false /* filterOnlyVisibleRecents */)));
|
||||
}
|
||||
return gestureState;
|
||||
|
@ -660,7 +661,7 @@ public class TouchInteractionService extends Service implements PluginListener<O
|
|||
if (AssistantUtilities.isExcludedAssistant(gestureState.getRunningTask())) {
|
||||
// In the case where we are in the excluded assistant state, ignore it and treat the
|
||||
// running activity as the task behind the assistant
|
||||
gestureState.updateRunningTask(TraceHelper.whitelistIpcs("getRunningTask.assistant",
|
||||
gestureState.updateRunningTask(TraceHelper.allowIpcs("getRunningTask.assistant",
|
||||
() -> mAM.getRunningTask(true /* filterOnlyVisibleRecents */)));
|
||||
ComponentName homeComponent = mOverviewComponentObserver.getHomeIntent().getComponent();
|
||||
ComponentName runningComponent =
|
||||
|
@ -771,13 +772,7 @@ public class TouchInteractionService extends Service implements PluginListener<O
|
|||
mOverviewComponentObserver.getActivityInterface();
|
||||
final Intent overviewIntent = new Intent(
|
||||
mOverviewComponentObserver.getOverviewIntentIgnoreSysUiState());
|
||||
if (activityInterface.getCreatedActivity() == null) {
|
||||
// Make sure that UI states will be initialized.
|
||||
activityInterface.createActivityInitListener((wasVisible) -> {
|
||||
AppLaunchTracker.INSTANCE.get(TouchInteractionService.this);
|
||||
return false;
|
||||
}).register(overviewIntent);
|
||||
} else if (fromInit) {
|
||||
if (activityInterface.getCreatedActivity() != null && fromInit) {
|
||||
// The activity has been created before the initialization of overview service. It is
|
||||
// usually happens when booting or launcher is the top activity, so we should already
|
||||
// have the latest state.
|
||||
|
|
|
@ -63,12 +63,6 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity>
|
|||
mActivity.startHome();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldUseMultiWindowTaskSizeStrategy() {
|
||||
// Just use the activity task size for multi-window as well.
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* When starting gesture interaction from home, we add a temporary invisible tile corresponding
|
||||
* to the home task. This allows us to handle quick-switch similarly to a quick-switching
|
||||
|
@ -76,7 +70,7 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity>
|
|||
*/
|
||||
public void onGestureAnimationStartOnHome(RunningTaskInfo homeTaskInfo) {
|
||||
mHomeTaskInfo = homeTaskInfo;
|
||||
onGestureAnimationStart(homeTaskInfo == null ? -1 : homeTaskInfo.taskId);
|
||||
onGestureAnimationStart(homeTaskInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -107,14 +101,15 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity>
|
|||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldAddDummyTaskView(int runningTaskId) {
|
||||
if (mHomeTaskInfo != null && mHomeTaskInfo.taskId == runningTaskId
|
||||
protected boolean shouldAddDummyTaskView(RunningTaskInfo runningTaskInfo) {
|
||||
if (mHomeTaskInfo != null && runningTaskInfo != null &&
|
||||
mHomeTaskInfo.taskId == runningTaskInfo.taskId
|
||||
&& getTaskViewCount() == 0) {
|
||||
// Do not add a dummy task if we are running over home with empty recents, so that we
|
||||
// show the empty recents message instead of showing a dummy task and later removing it.
|
||||
return false;
|
||||
}
|
||||
return super.shouldAddDummyTaskView(runningTaskId);
|
||||
return super.shouldAddDummyTaskView(runningTaskInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -99,7 +99,8 @@ public class AccessibilityInputConsumer extends DelegateInputConsumer {
|
|||
case ACTION_POINTER_DOWN: {
|
||||
if (mState == STATE_INACTIVE) {
|
||||
int pointerIndex = ev.getActionIndex();
|
||||
if (mDeviceState.isInSwipeUpTouchRegion(ev, pointerIndex)
|
||||
if (mDeviceState.getRotationTouchHelper()
|
||||
.isInSwipeUpTouchRegion(ev, pointerIndex)
|
||||
&& mDelegate.allowInterceptByParent()) {
|
||||
setActive(ev);
|
||||
|
||||
|
|
|
@ -147,7 +147,7 @@ public class DeviceLockedInputConsumer implements InputConsumer,
|
|||
if (!mThresholdCrossed) {
|
||||
// Cancel interaction in case of multi-touch interaction
|
||||
int ptrIdx = ev.getActionIndex();
|
||||
if (!mDeviceState.isInSwipeUpTouchRegion(ev, ptrIdx)) {
|
||||
if (!mDeviceState.getRotationTouchHelper().isInSwipeUpTouchRegion(ev, ptrIdx)) {
|
||||
int action = ev.getAction();
|
||||
ev.setAction(ACTION_CANCEL);
|
||||
finishTouchTracking(ev);
|
||||
|
|
|
@ -59,6 +59,7 @@ import com.android.quickstep.GestureState;
|
|||
import com.android.quickstep.InputConsumer;
|
||||
import com.android.quickstep.RecentsAnimationCallbacks;
|
||||
import com.android.quickstep.RecentsAnimationDeviceState;
|
||||
import com.android.quickstep.RotationTouchHelper;
|
||||
import com.android.quickstep.TaskAnimationManager;
|
||||
import com.android.quickstep.util.ActiveGestureLog;
|
||||
import com.android.quickstep.util.CachedEventDispatcher;
|
||||
|
@ -86,6 +87,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
|||
private final NavBarPosition mNavBarPosition;
|
||||
private final TaskAnimationManager mTaskAnimationManager;
|
||||
private final GestureState mGestureState;
|
||||
private final RotationTouchHelper mRotationTouchHelper;
|
||||
private RecentsAnimationCallbacks mActiveCallbacks;
|
||||
private final CachedEventDispatcher mRecentsViewDispatcher = new CachedEventDispatcher();
|
||||
private final InputMonitorCompat mInputMonitorCompat;
|
||||
|
@ -163,6 +165,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
|||
|
||||
mPassedPilferInputSlop = mPassedWindowMoveSlop = continuingPreviousGesture;
|
||||
mDisableHorizontalSwipe = !mPassedPilferInputSlop && disableHorizontalSwipe;
|
||||
mRotationTouchHelper = mDeviceState.getRotationTouchHelper();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -230,7 +233,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
|||
if (!mPassedPilferInputSlop) {
|
||||
// Cancel interaction in case of multi-touch interaction
|
||||
int ptrIdx = ev.getActionIndex();
|
||||
if (!mDeviceState.isInSwipeUpTouchRegion(ev, ptrIdx)) {
|
||||
if (!mRotationTouchHelper.isInSwipeUpTouchRegion(ev, ptrIdx)) {
|
||||
forceCancelGesture(ev);
|
||||
}
|
||||
}
|
||||
|
@ -424,7 +427,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
|||
|
||||
@Override
|
||||
public void notifyOrientationSetup() {
|
||||
mDeviceState.onStartGesture();
|
||||
mRotationTouchHelper.onStartGesture();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -205,13 +205,15 @@ public class StaggeredWorkspaceAnim {
|
|||
ResourceProvider rp = DynamicResource.provider(v.getContext());
|
||||
float stiffness = rp.getFloat(R.dimen.staggered_stiffness);
|
||||
float damping = rp.getFloat(R.dimen.staggered_damping_ratio);
|
||||
float endTransY = 0;
|
||||
float springVelocity = Math.abs(mVelocity) * Math.signum(endTransY - mSpringTransY);
|
||||
ValueAnimator springTransY = new SpringAnimationBuilder(v.getContext())
|
||||
.setStiffness(stiffness)
|
||||
.setDampingRatio(damping)
|
||||
.setMinimumVisibleChange(1f)
|
||||
.setStartValue(mSpringTransY)
|
||||
.setEndValue(0)
|
||||
.setStartVelocity(mVelocity)
|
||||
.setEndValue(endTransY)
|
||||
.setStartVelocity(springVelocity)
|
||||
.build(v, VIEW_TRANSLATE_Y);
|
||||
springTransY.setStartDelay(startDelay);
|
||||
springTransY.addListener(new AnimatorListenerAdapter() {
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
package com.android.quickstep.util;
|
||||
|
||||
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
|
||||
import static com.android.launcher3.states.RotationHelper.deltaRotation;
|
||||
import static com.android.launcher3.touch.PagedOrientationHandler.MATRIX_POST_TRANSLATE;
|
||||
import static com.android.quickstep.util.RecentsOrientedState.postDisplayRotation;
|
||||
|
@ -197,6 +198,15 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy {
|
|||
return mTempRectF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current task bounds in the Launcher coordinate space.
|
||||
*/
|
||||
public RectF getCurrentRect() {
|
||||
RectF result = getCurrentCropRect();
|
||||
mMatrix.mapRect(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public RecentsOrientedState getOrientationState() {
|
||||
return mOrientationState;
|
||||
}
|
||||
|
@ -295,6 +305,10 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy {
|
|||
builder.withMatrix(mMatrix)
|
||||
.withWindowCrop(mTmpCropRect)
|
||||
.withCornerRadius(getCurrentCornerRadius());
|
||||
|
||||
if (ENABLE_QUICKSTEP_LIVE_TILE.get() && params.getRecentsSurface() != null) {
|
||||
builder.withRelativeLayerTo(params.getRecentsSurface(), Integer.MAX_VALUE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
package com.android.quickstep.util;
|
||||
|
||||
import android.util.FloatProperty;
|
||||
import android.view.SurfaceControl;
|
||||
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.anim.Interpolators;
|
||||
|
@ -58,6 +59,7 @@ public class TransformParams {
|
|||
private float mCornerRadius;
|
||||
private RemoteAnimationTargets mTargetSet;
|
||||
private SurfaceTransactionApplier mSyncTransactionApplier;
|
||||
private SurfaceControl mRecentsSurface;
|
||||
|
||||
private BuilderProxy mHomeBuilderProxy = BuilderProxy.ALWAYS_VISIBLE;
|
||||
private BuilderProxy mBaseBuilderProxy = BuilderProxy.ALWAYS_VISIBLE;
|
||||
|
@ -138,6 +140,8 @@ public class TransformParams {
|
|||
public SurfaceParams[] createSurfaceParams(BuilderProxy proxy) {
|
||||
RemoteAnimationTargets targets = mTargetSet;
|
||||
SurfaceParams[] surfaceParams = new SurfaceParams[targets.unfilteredApps.length];
|
||||
mRecentsSurface = getRecentsSurface(targets);
|
||||
|
||||
for (int i = 0; i < targets.unfilteredApps.length; i++) {
|
||||
RemoteAnimationTargetCompat app = targets.unfilteredApps[i];
|
||||
SurfaceParams.Builder builder = new SurfaceParams.Builder(app.leash);
|
||||
|
@ -165,6 +169,20 @@ public class TransformParams {
|
|||
return surfaceParams;
|
||||
}
|
||||
|
||||
private static SurfaceControl getRecentsSurface(RemoteAnimationTargets targets) {
|
||||
for (int i = 0; i < targets.unfilteredApps.length; i++) {
|
||||
RemoteAnimationTargetCompat app = targets.unfilteredApps[i];
|
||||
if (app.mode == targets.targetMode) {
|
||||
if (app.activityType == RemoteAnimationTargetCompat.ACTIVITY_TYPE_RECENTS) {
|
||||
return app.leash.getSurfaceControl();
|
||||
}
|
||||
} else {
|
||||
return app.leash.getSurfaceControl();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Pubic getters so outside packages can read the values.
|
||||
|
||||
public float getProgress() {
|
||||
|
@ -179,6 +197,10 @@ public class TransformParams {
|
|||
return mCornerRadius;
|
||||
}
|
||||
|
||||
public SurfaceControl getRecentsSurface() {
|
||||
return mRecentsSurface;
|
||||
}
|
||||
|
||||
public RemoteAnimationTargets getTargetSet() {
|
||||
return mTargetSet;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
package com.android.quickstep.views;
|
||||
|
||||
import static com.android.launcher3.LauncherState.ALL_APPS;
|
||||
import static com.android.launcher3.LauncherState.NORMAL;
|
||||
import static com.android.launcher3.anim.Interpolators.ACCEL;
|
||||
import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
|
@ -42,8 +43,10 @@ import com.android.launcher3.DeviceProfile;
|
|||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.allapps.AllAppsTransitionController;
|
||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||
import com.android.launcher3.anim.Interpolators;
|
||||
import com.android.launcher3.anim.PendingAnimation;
|
||||
import com.android.launcher3.dragndrop.DragLayer;
|
||||
import com.android.launcher3.states.StateAnimationConfig;
|
||||
import com.android.launcher3.util.Themes;
|
||||
|
@ -51,6 +54,7 @@ import com.android.quickstep.util.MultiValueUpdateListener;
|
|||
|
||||
/**
|
||||
* View used to educate the user on how to access All Apps when in No Nav Button navigation mode.
|
||||
* Consumes all touches until after the animation is completed and the view is removed.
|
||||
*/
|
||||
public class AllAppsEduView extends AbstractFloatingView {
|
||||
|
||||
|
@ -110,9 +114,19 @@ public class AllAppsEduView extends AbstractFloatingView {
|
|||
return (type & TYPE_ALL_APPS_EDU) != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onBackPressed() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canInterceptEventsInSystemGestureRegion() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
|
||||
return mAnimation != null && mAnimation.isRunning();
|
||||
return true;
|
||||
}
|
||||
|
||||
private void playAnimation() {
|
||||
|
@ -139,7 +153,12 @@ public class AllAppsEduView extends AbstractFloatingView {
|
|||
config.userControlled = false;
|
||||
AnimatorPlaybackController stateAnimationController =
|
||||
mLauncher.getStateManager().createAnimationToNewWorkspace(ALL_APPS, config);
|
||||
float maxAllAppsProgress = 0.15f;
|
||||
float maxAllAppsProgress = mLauncher.getDeviceProfile().isLandscape ? 0.35f : 0.15f;
|
||||
|
||||
AllAppsTransitionController allAppsController = mLauncher.getAllAppsController();
|
||||
PendingAnimation allAppsAlpha = new PendingAnimation(config.duration);
|
||||
allAppsController.setAlphas(ALL_APPS, config, allAppsAlpha);
|
||||
mAnimation.play(allAppsAlpha.buildAnim());
|
||||
|
||||
ValueAnimator intro = ValueAnimator.ofFloat(0, 1f);
|
||||
intro.setInterpolator(LINEAR);
|
||||
|
@ -191,7 +210,8 @@ public class AllAppsEduView extends AbstractFloatingView {
|
|||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
mAnimation = null;
|
||||
stateAnimationController.dispatchOnCancel();
|
||||
// Handles cancelling the animation used to hint towards All Apps.
|
||||
mLauncher.getStateManager().goToState(NORMAL, false);
|
||||
handleClose(false);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -31,7 +31,6 @@ import android.animation.ObjectAnimator;
|
|||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.os.UserHandle;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.Surface;
|
||||
|
@ -41,20 +40,15 @@ import com.android.launcher3.BaseQuickstepLauncher;
|
|||
import com.android.launcher3.Hotseat;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.anim.Interpolators;
|
||||
import com.android.launcher3.appprediction.PredictionUiStateManager;
|
||||
import com.android.launcher3.appprediction.PredictionUiStateManager.Client;
|
||||
import com.android.launcher3.model.AppLaunchTracker;
|
||||
import com.android.launcher3.statehandlers.DepthController;
|
||||
import com.android.launcher3.statemanager.StateManager.StateListener;
|
||||
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
|
||||
import com.android.launcher3.util.TraceHelper;
|
||||
import com.android.launcher3.views.ScrimView;
|
||||
import com.android.quickstep.LauncherActivityInterface;
|
||||
import com.android.quickstep.SysUINavigationMode;
|
||||
import com.android.quickstep.util.TransformParams;
|
||||
import com.android.systemui.plugins.PluginListener;
|
||||
import com.android.systemui.plugins.RecentsExtraCard;
|
||||
import com.android.systemui.shared.recents.model.Task;
|
||||
|
||||
/**
|
||||
* {@link RecentsView} used in Launcher activity
|
||||
|
@ -180,18 +174,6 @@ public class LauncherRecentsView extends RecentsView<BaseQuickstepLauncher>
|
|||
super.onTaskLaunchAnimationEnd(success);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTaskLaunched(Task task) {
|
||||
UserHandle user = UserHandle.of(task.key.userId);
|
||||
AppLaunchTracker.INSTANCE.get(getContext()).onStartApp(task.getTopComponent(), user,
|
||||
AppLaunchTracker.CONTAINER_OVERVIEW);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldUseMultiWindowTaskSizeStrategy() {
|
||||
return TraceHelper.whitelistIpcs("isInMultiWindowMode", mActivity::isInMultiWindowMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void scrollTo(int x, int y) {
|
||||
super.scrollTo(x, y);
|
||||
|
@ -237,9 +219,6 @@ public class LauncherRecentsView extends RecentsView<BaseQuickstepLauncher>
|
|||
super.reset();
|
||||
|
||||
setLayoutRotation(Surface.ROTATION_0, Surface.ROTATION_0);
|
||||
// We are moving to home or some other UI with no recents. Switch back to the home client,
|
||||
// the home predictions should have been updated when the activity was resumed.
|
||||
PredictionUiStateManager.INSTANCE.get(getContext()).switchClient(Client.HOME);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -70,12 +70,14 @@ public class OverviewActionsView<T extends OverlayUICallbacks> extends FrameLayo
|
|||
|
||||
@IntDef(flag = true, value = {
|
||||
DISABLED_SCROLLING,
|
||||
DISABLED_ROTATED})
|
||||
DISABLED_ROTATED,
|
||||
DISABLED_NO_THUMBNAIL})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface ActionsDisabledFlags { }
|
||||
|
||||
public static final int DISABLED_SCROLLING = 1 << 0;
|
||||
public static final int DISABLED_ROTATED = 1 << 1;
|
||||
public static final int DISABLED_NO_THUMBNAIL = 1 << 2;
|
||||
|
||||
private static final int INDEX_CONTENT_ALPHA = 0;
|
||||
private static final int INDEX_VISIBILITY_ALPHA = 1;
|
||||
|
|
|
@ -55,10 +55,8 @@ import android.animation.LayoutTransition.TransitionListener;
|
|||
import android.animation.ObjectAnimator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.ActivityManager;
|
||||
import android.content.ComponentName;
|
||||
import android.app.ActivityManager.RunningTaskInfo;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Point;
|
||||
|
@ -135,6 +133,7 @@ import com.android.quickstep.util.TransformParams;
|
|||
import com.android.systemui.plugins.ResourceProvider;
|
||||
import com.android.systemui.shared.recents.IPinnedStackAnimationListener;
|
||||
import com.android.systemui.shared.recents.model.Task;
|
||||
import com.android.systemui.shared.recents.model.Task.TaskKey;
|
||||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
import com.android.systemui.shared.system.ActivityManagerWrapper;
|
||||
import com.android.systemui.shared.system.LauncherEventUtil;
|
||||
|
@ -147,7 +146,7 @@ import java.util.function.Consumer;
|
|||
/**
|
||||
* A list of recent tasks.
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.P)
|
||||
@TargetApi(Build.VERSION_CODES.R)
|
||||
public abstract class RecentsView<T extends StatefulActivity> extends PagedView implements
|
||||
Insettable, TaskThumbnailCache.HighResLoadingState.HighResLoadingStateChangedCallback,
|
||||
InvariantDeviceProfile.OnIDPChangeListener, TaskVisualsChangeListener,
|
||||
|
@ -377,7 +376,7 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
|
|||
mOrientationState.setMultiWindowMode(inMultiWindowMode);
|
||||
setLayoutRotation(mOrientationState.getTouchRotation(),
|
||||
mOrientationState.getDisplayRotation());
|
||||
rotateAllChildTasks();
|
||||
updateChildTaskOrientations();
|
||||
}
|
||||
if (!inMultiWindowMode && mOverviewStateEnabled) {
|
||||
// TODO: Re-enable layout transitions for addition of the unpinned task
|
||||
|
@ -1041,13 +1040,13 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
|
|||
/**
|
||||
* Called when a gesture from an app is starting.
|
||||
*/
|
||||
public void onGestureAnimationStart(int runningTaskId) {
|
||||
public void onGestureAnimationStart(RunningTaskInfo runningTaskInfo) {
|
||||
// This needs to be called before the other states are set since it can create the task view
|
||||
if (mOrientationState.setGestureActive(true)) {
|
||||
updateOrientationHandler();
|
||||
}
|
||||
|
||||
showCurrentTask(runningTaskId);
|
||||
showCurrentTask(runningTaskInfo);
|
||||
setEnableFreeScroll(false);
|
||||
setEnableDrawingLiveTile(false);
|
||||
setRunningTaskHidden(true);
|
||||
|
@ -1078,7 +1077,7 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
|
|||
pa.addListener(AnimationSuccessListener.forRunnable(() -> {
|
||||
setLayoutRotation(newRotation, mOrientationState.getDisplayRotation());
|
||||
mActivity.getDragLayer().recreateControllers();
|
||||
rotateAllChildTasks();
|
||||
updateChildTaskOrientations();
|
||||
setRecentsChangedOrientation(false).start();
|
||||
}));
|
||||
pa.start();
|
||||
|
@ -1099,7 +1098,7 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
|
|||
}
|
||||
|
||||
|
||||
private void rotateAllChildTasks() {
|
||||
private void updateChildTaskOrientations() {
|
||||
for (int i = 0; i < getTaskViewCount(); i++) {
|
||||
getTaskViewAt(i).setOrientationState(mOrientationState);
|
||||
}
|
||||
|
@ -1127,8 +1126,8 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
|
|||
/**
|
||||
* Returns true if we should add a dummy taskView for the running task id
|
||||
*/
|
||||
protected boolean shouldAddDummyTaskView(int runningTaskId) {
|
||||
return getTaskView(runningTaskId) == null;
|
||||
protected boolean shouldAddDummyTaskView(RunningTaskInfo runningTaskInfo) {
|
||||
return runningTaskInfo != null && getTaskView(runningTaskInfo.taskId) == null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1137,8 +1136,8 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
|
|||
* All subsequent calls to reload will keep the task as the first item until {@link #reset()}
|
||||
* is called. Also scrolls the view to this task.
|
||||
*/
|
||||
public void showCurrentTask(int runningTaskId) {
|
||||
if (shouldAddDummyTaskView(runningTaskId)) {
|
||||
public void showCurrentTask(RunningTaskInfo runningTaskInfo) {
|
||||
if (shouldAddDummyTaskView(runningTaskInfo)) {
|
||||
boolean wasEmpty = getChildCount() == 0;
|
||||
// Add an empty view for now until the task plan is loaded and applied
|
||||
final TaskView taskView = mTaskViewPool.getView();
|
||||
|
@ -1148,10 +1147,7 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
|
|||
}
|
||||
// The temporary running task is only used for the duration between the start of the
|
||||
// gesture and the task list is loaded and applied
|
||||
mTmpRunningTask = new Task(new Task.TaskKey(runningTaskId, 0, new Intent(),
|
||||
new ComponentName(getContext(), getClass()), 0, 0), null, null, "", "", 0, 0,
|
||||
false, true, false, false, new ActivityManager.TaskDescription(), 0,
|
||||
new ComponentName("", ""), false);
|
||||
mTmpRunningTask = Task.from(new TaskKey(runningTaskInfo), runningTaskInfo, false);
|
||||
taskView.bind(mTmpRunningTask, mOrientationState);
|
||||
|
||||
// Measure and layout immediately so that the scroll values is updated instantly
|
||||
|
@ -1162,7 +1158,7 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
|
|||
}
|
||||
|
||||
boolean runningTaskTileHidden = mRunningTaskTileHidden;
|
||||
setCurrentTask(runningTaskId);
|
||||
setCurrentTask(runningTaskInfo == null ? -1 : runningTaskInfo.taskId);
|
||||
setCurrentPage(getRunningTaskIndex());
|
||||
setRunningTaskViewShowScreenshot(false);
|
||||
setRunningTaskHidden(runningTaskTileHidden);
|
||||
|
@ -1652,6 +1648,9 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
|
|||
super.setVisibility(visibility);
|
||||
if (mActionsView != null) {
|
||||
mActionsView.updateHiddenFlags(HIDDEN_NO_RECENTS, visibility != VISIBLE);
|
||||
if (visibility != VISIBLE) {
|
||||
mActionsView.updateDisabledFlags(OverviewActionsView.DISABLED_SCROLLING, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1680,10 +1679,11 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
|
|||
: View.LAYOUT_DIRECTION_RTL);
|
||||
mClearAllButton.setRotation(mOrientationHandler.getDegreesRotated());
|
||||
mActivity.getDragLayer().recreateControllers();
|
||||
boolean isInLandscape = mOrientationState.getTouchRotation() != 0
|
||||
boolean isInLandscape = mOrientationState.getTouchRotation() != ROTATION_0
|
||||
|| mOrientationState.getRecentsActivityRotation() != ROTATION_0;
|
||||
mActionsView.updateHiddenFlags(HIDDEN_NON_ZERO_ROTATION,
|
||||
!mOrientationState.canRecentsActivityRotate() && isInLandscape);
|
||||
updateChildTaskOrientations();
|
||||
resetPaddingFromTaskSize();
|
||||
requestLayout();
|
||||
// Reapply the current page to update page scrolls.
|
||||
|
@ -1998,19 +1998,12 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
|
|||
protected void onTaskLaunchAnimationUpdate(float progress, TaskView tv) {
|
||||
}
|
||||
|
||||
public abstract boolean shouldUseMultiWindowTaskSizeStrategy();
|
||||
|
||||
protected void onTaskLaunchAnimationEnd(boolean success) {
|
||||
if (success) {
|
||||
resetTaskVisuals();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when task activity is launched
|
||||
*/
|
||||
public void onTaskLaunched(Task task){ }
|
||||
|
||||
@Override
|
||||
protected void notifyPageSwitchListener(int prevPage) {
|
||||
super.notifyPageSwitchListener(prevPage);
|
||||
|
|
|
@ -169,7 +169,9 @@ public class TaskMenuView extends AbstractFloatingView {
|
|||
}
|
||||
if (mIsOpen) {
|
||||
mOptionLayout.removeAllViews();
|
||||
populateAndLayoutMenu();
|
||||
if (!populateAndLayoutMenu()) {
|
||||
close(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -186,14 +188,22 @@ public class TaskMenuView extends AbstractFloatingView {
|
|||
}
|
||||
mActivity.getDragLayer().addView(this);
|
||||
mTaskView = taskView;
|
||||
populateAndLayoutMenu();
|
||||
if (!populateAndLayoutMenu()) {
|
||||
return false;
|
||||
}
|
||||
post(this::animateOpen);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void populateAndLayoutMenu() {
|
||||
/** @return true if successfully able to populate task view menu, false otherwise */
|
||||
private boolean populateAndLayoutMenu() {
|
||||
if (mTaskView.getTask().icon == null) {
|
||||
// Icon may not be loaded
|
||||
return false;
|
||||
}
|
||||
addMenuOptions(mTaskView);
|
||||
orientAroundTaskView(mTaskView);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void addMenuOptions(TaskView taskView) {
|
||||
|
@ -240,8 +250,10 @@ public class TaskMenuView extends AbstractFloatingView {
|
|||
setLayoutParams(params);
|
||||
setScaleX(taskView.getScaleX());
|
||||
setScaleY(taskView.getScaleY());
|
||||
boolean canActivityRotate = taskView.getRecentsView()
|
||||
.mOrientationState.canRecentsActivityRotate();
|
||||
mOptionLayout.setOrientation(orientationHandler
|
||||
.getTaskMenuLayoutOrientation(mOptionLayout));
|
||||
.getTaskMenuLayoutOrientation(canActivityRotate, mOptionLayout));
|
||||
setPosition(sTempRect.left - insets.left, sTempRect.top - insets.top,
|
||||
taskView.getPagedOrientationHandler());
|
||||
}
|
||||
|
|
|
@ -357,7 +357,7 @@ public class TaskThumbnailView extends View implements PluginListener<OverviewSc
|
|||
}
|
||||
|
||||
private void updateOverlay() {
|
||||
if (mOverlayEnabled && mBitmapShader != null && mThumbnailData != null) {
|
||||
if (mOverlayEnabled) {
|
||||
mOverlay.initOverlay(mTask, mThumbnailData, mPreviewPositionHelper.mMatrix,
|
||||
mPreviewPositionHelper.mIsOrientationChanged);
|
||||
} else {
|
||||
|
|
|
@ -30,8 +30,7 @@ import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
|
|||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
import static com.android.launcher3.anim.Interpolators.TOUCH_RESPONSE_INTERPOLATOR;
|
||||
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent
|
||||
.LAUNCHER_TASK_ICON_TAP_OR_LONGPRESS;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_ICON_TAP_OR_LONGPRESS;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_TAP;
|
||||
|
||||
import android.animation.Animator;
|
||||
|
@ -385,7 +384,6 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
|
|||
}
|
||||
}, resultCallbackHandler);
|
||||
}
|
||||
getRecentsView().onTaskLaunched(mTask);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
<?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.
|
||||
-->
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="oval">
|
||||
<solid android:color="#FFFFFFFF" />
|
||||
</shape>
|
|
@ -24,6 +24,14 @@
|
|||
android:layout_height="match_parent"
|
||||
android:background="@drawable/gesture_tutorial_ripple"/>
|
||||
|
||||
<com.android.launcher3.views.ClipIconView
|
||||
android:id="@+id/gesture_tutorial_fake_icon_view"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:background="@drawable/bg_circle"
|
||||
android:backgroundTint="@color/gesture_tutorial_fake_task_view_color"
|
||||
android:visibility="invisible" />
|
||||
|
||||
<View
|
||||
android:id="@+id/gesture_tutorial_fake_task_view"
|
||||
android:layout_width="match_parent"
|
||||
|
@ -41,81 +49,81 @@
|
|||
android:id="@+id/gesture_tutorial_fragment_close_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="18dp"
|
||||
android:layout_marginTop="30dp"
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:background="@android:color/transparent"
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginTop="30dp"
|
||||
android:accessibilityTraversalAfter="@id/gesture_tutorial_fragment_titles_container"
|
||||
android:background="@android:color/transparent"
|
||||
android:contentDescription="@string/gesture_tutorial_close_button_content_description"
|
||||
android:tint="?android:attr/textColorPrimary"
|
||||
android:src="@drawable/gesture_tutorial_close_button"/>
|
||||
android:padding="18dp"
|
||||
android:src="@drawable/gesture_tutorial_close_button"
|
||||
android:tint="?android:attr/textColorPrimary"/>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/gesture_tutorial_fragment_titles_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="70dp"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_marginTop="70dp"
|
||||
android:focusable="true"
|
||||
android:gravity="center_horizontal"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/gesture_tutorial_fragment_title_view"
|
||||
style="@style/TextAppearance.GestureTutorial.Title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/gesture_tutorial_title_margin_start_end"
|
||||
android:layout_marginEnd="@dimen/gesture_tutorial_title_margin_start_end"
|
||||
style="@style/TextAppearance.GestureTutorial.Title"/>
|
||||
android:layout_marginEnd="@dimen/gesture_tutorial_title_margin_start_end"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/gesture_tutorial_fragment_subtitle_view"
|
||||
style="@style/TextAppearance.GestureTutorial.Subtitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginStart="@dimen/gesture_tutorial_subtitle_margin_start_end"
|
||||
android:layout_marginEnd="@dimen/gesture_tutorial_subtitle_margin_start_end"
|
||||
style="@style/TextAppearance.GestureTutorial.Subtitle"/>
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginEnd="@dimen/gesture_tutorial_subtitle_margin_start_end"/>
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/gesture_tutorial_fragment_feedback_view"
|
||||
style="@style/TextAppearance.GestureTutorial.Feedback"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:layout_centerHorizontal="true"
|
||||
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"
|
||||
style="@style/TextAppearance.GestureTutorial.Feedback"/>
|
||||
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 -->
|
||||
<Button
|
||||
android:id="@+id/gesture_tutorial_fragment_action_button"
|
||||
style="@style/TextAppearance.GestureTutorial.ButtonLabel"
|
||||
android:layout_width="142dp"
|
||||
android:layout_height="49dp"
|
||||
android:layout_marginEnd="@dimen/gesture_tutorial_button_margin_start_end"
|
||||
android:layout_marginBottom="48dp"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:stateListAnimator="@null"
|
||||
android:layout_marginEnd="@dimen/gesture_tutorial_button_margin_start_end"
|
||||
android:layout_marginBottom="48dp"
|
||||
android:background="@drawable/gesture_tutorial_action_button_background"
|
||||
android:foreground="?android:attr/selectableItemBackgroundBorderless"
|
||||
style="@style/TextAppearance.GestureTutorial.ButtonLabel"/>
|
||||
android:stateListAnimator="@null"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/gesture_tutorial_fragment_action_text_button"
|
||||
style="@style/TextAppearance.GestureTutorial.TextButtonLabel"
|
||||
android:layout_width="142dp"
|
||||
android:layout_height="49dp"
|
||||
android:layout_marginStart="@dimen/gesture_tutorial_button_margin_start_end"
|
||||
android:layout_marginBottom="48dp"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:stateListAnimator="@null"
|
||||
android:layout_marginStart="@dimen/gesture_tutorial_button_margin_start_end"
|
||||
android:layout_marginBottom="48dp"
|
||||
android:background="@null"
|
||||
android:foreground="?android:attr/selectableItemBackgroundBorderless"
|
||||
style="@style/TextAppearance.GestureTutorial.TextButtonLabel"/>
|
||||
android:stateListAnimator="@null"/>
|
||||
</RelativeLayout>
|
|
@ -17,6 +17,7 @@ package com.android.quickstep;
|
|||
|
||||
import static com.android.launcher3.util.LauncherUIHelper.doLayout;
|
||||
|
||||
import android.app.ActivityManager.RunningTaskInfo;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Bitmap.Config;
|
||||
|
||||
|
@ -50,7 +51,7 @@ public class RecentsActivityTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testRecets_showCurrentTask() {
|
||||
public void testRecents_showCurrentTask() {
|
||||
ActivityController<RecentsActivity> controller =
|
||||
Robolectric.buildActivity(RecentsActivity.class);
|
||||
|
||||
|
@ -58,7 +59,10 @@ public class RecentsActivityTest {
|
|||
doLayout(activity);
|
||||
|
||||
FallbackRecentsView frv = activity.getOverviewPanel();
|
||||
frv.showCurrentTask(22);
|
||||
|
||||
RunningTaskInfo dummyTask = new RunningTaskInfo();
|
||||
dummyTask.taskId = 22;
|
||||
frv.showCurrentTask(dummyTask);
|
||||
doLayout(activity);
|
||||
|
||||
ThumbnailData thumbnailData = new ThumbnailData();
|
||||
|
|
|
@ -157,6 +157,12 @@ public abstract class BaseQuickstepLauncher extends Launcher
|
|||
@Override
|
||||
protected void onDeferredResumed() {
|
||||
super.onDeferredResumed();
|
||||
handlePendingActivityRequest();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handlePendingActivityRequest() {
|
||||
super.handlePendingActivityRequest();
|
||||
if (mPendingActivityRequestCode != -1 && isInState(NORMAL)) {
|
||||
// Remove any active ProxyActivityStarter task and send RESULT_CANCELED to Launcher.
|
||||
onActivityResult(mPendingActivityRequestCode, RESULT_CANCELED, null);
|
||||
|
|
|
@ -16,8 +16,6 @@
|
|||
|
||||
package com.android.launcher3;
|
||||
|
||||
import static android.util.TypedValue.COMPLEX_UNIT_DIP;
|
||||
|
||||
import static com.android.launcher3.BaseActivity.INVISIBLE_ALL;
|
||||
import static com.android.launcher3.BaseActivity.INVISIBLE_BY_APP_TRANSITIONS;
|
||||
import static com.android.launcher3.BaseActivity.INVISIBLE_BY_PENDING_FLAGS;
|
||||
|
@ -62,7 +60,6 @@ import android.os.CancellationSignal;
|
|||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.util.Pair;
|
||||
import android.util.TypedValue;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
@ -879,10 +876,8 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans
|
|||
}
|
||||
});
|
||||
} else {
|
||||
float velocityDpPerS = DynamicResource.provider(mLauncher)
|
||||
float velocityPxPerS = DynamicResource.provider(mLauncher)
|
||||
.getDimension(R.dimen.unlock_staggered_velocity_dp_per_s);
|
||||
float velocityPxPerS = TypedValue.applyDimension(COMPLEX_UNIT_DIP,
|
||||
velocityDpPerS, mLauncher.getResources().getDisplayMetrics());
|
||||
anim.play(new StaggeredWorkspaceAnim(mLauncher, velocityPxPerS, false)
|
||||
.getAnimators());
|
||||
}
|
||||
|
|
|
@ -150,16 +150,9 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
|
|||
return deviceState.isInDeferredGestureRegion(ev);
|
||||
}
|
||||
|
||||
public abstract void onExitOverview(RecentsAnimationDeviceState deviceState,
|
||||
public abstract void onExitOverview(RotationTouchHelper deviceState,
|
||||
Runnable exitRunnable);
|
||||
|
||||
/**
|
||||
* Updates the prediction state to the overview state.
|
||||
*/
|
||||
public void updateOverviewPredictionState() {
|
||||
// By public overview predictions are not supported
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for containerType in {@link com.android.launcher3.logging.UserEventDispatcher}
|
||||
*/
|
||||
|
|
|
@ -16,11 +16,9 @@
|
|||
package com.android.quickstep;
|
||||
|
||||
import static android.content.Intent.ACTION_USER_UNLOCKED;
|
||||
import static android.view.Surface.ROTATION_0;
|
||||
|
||||
import static com.android.launcher3.util.DefaultDisplay.CHANGE_ALL;
|
||||
import static com.android.launcher3.util.DefaultDisplay.CHANGE_FRAME_DELAY;
|
||||
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
|
||||
import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
|
||||
import static com.android.quickstep.SysUINavigationMode.Mode.THREE_BUTTONS;
|
||||
import static com.android.quickstep.SysUINavigationMode.Mode.TWO_BUTTONS;
|
||||
|
@ -49,23 +47,19 @@ import android.os.UserManager;
|
|||
import android.provider.Settings;
|
||||
import android.text.TextUtils;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.OrientationEventListener;
|
||||
|
||||
import androidx.annotation.BinderThread;
|
||||
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.testing.TestProtocol;
|
||||
import com.android.launcher3.util.DefaultDisplay;
|
||||
import com.android.launcher3.util.SecureSettingsObserver;
|
||||
import com.android.quickstep.SysUINavigationMode.NavigationModeChangeListener;
|
||||
import com.android.quickstep.util.NavBarPosition;
|
||||
import com.android.quickstep.util.RecentsOrientedState;
|
||||
import com.android.systemui.shared.system.ActivityManagerWrapper;
|
||||
import com.android.systemui.shared.system.QuickStepContract;
|
||||
import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
|
||||
import com.android.systemui.shared.system.SystemGestureExclusionListenerCompat;
|
||||
import com.android.systemui.shared.system.TaskStackChangeListener;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
|
@ -83,7 +77,7 @@ public class RecentsAnimationDeviceState implements
|
|||
private final SysUINavigationMode mSysUiNavMode;
|
||||
private final DefaultDisplay mDefaultDisplay;
|
||||
private final int mDisplayId;
|
||||
private int mDisplayRotation;
|
||||
private final RotationTouchHelper mRotationTouchHelper;
|
||||
|
||||
private final ArrayList<Runnable> mOnDestroyActions = new ArrayList<>();
|
||||
|
||||
|
@ -107,76 +101,10 @@ public class RecentsAnimationDeviceState implements
|
|||
}
|
||||
};
|
||||
|
||||
private TaskStackChangeListener mFrozenTaskListener = new TaskStackChangeListener() {
|
||||
@Override
|
||||
public void onRecentTaskListFrozenChanged(boolean frozen) {
|
||||
mTaskListFrozen = frozen;
|
||||
if (frozen || mInOverview) {
|
||||
return;
|
||||
}
|
||||
enableMultipleRegions(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityRotation(int displayId) {
|
||||
super.onActivityRotation(displayId);
|
||||
// This always gets called before onDisplayInfoChanged() so we know how to process
|
||||
// the rotation in that method. This is done to avoid having a race condition between
|
||||
// the sensor readings and onDisplayInfoChanged() call
|
||||
if (displayId != mDisplayId) {
|
||||
return;
|
||||
}
|
||||
|
||||
mPrioritizeDeviceRotation = true;
|
||||
if (mInOverview) {
|
||||
// reset, launcher must be rotating
|
||||
mExitOverviewRunnable.run();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private Runnable mExitOverviewRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mInOverview = false;
|
||||
enableMultipleRegions(false);
|
||||
}
|
||||
};
|
||||
|
||||
private OrientationTouchTransformer mOrientationTouchTransformer;
|
||||
/**
|
||||
* Used to listen for when the device rotates into the orientation of the current
|
||||
* foreground app. For example, if a user quickswitches from a portrait to a fixed landscape
|
||||
* app and then rotates rotates the device to match that orientation, this triggers calls to
|
||||
* sysui to adjust the navbar.
|
||||
*/
|
||||
private OrientationEventListener mOrientationListener;
|
||||
private int mSensorRotation = ROTATION_0;
|
||||
/**
|
||||
* This is the configuration of the foreground app or the app that will be in the foreground
|
||||
* once a quickstep gesture finishes.
|
||||
*/
|
||||
private int mCurrentAppRotation = -1;
|
||||
/**
|
||||
* This flag is set to true when the device physically changes orientations. When true,
|
||||
* we will always report the current rotation of the foreground app whenever the display
|
||||
* changes, as it would indicate the user's intention to rotate the foreground app.
|
||||
*/
|
||||
private boolean mPrioritizeDeviceRotation = false;
|
||||
|
||||
private Region mExclusionRegion;
|
||||
private SystemGestureExclusionListenerCompat mExclusionListener;
|
||||
|
||||
private final List<ComponentName> mGestureBlockedActivities;
|
||||
private Runnable mOnDestroyFrozenTaskRunnable;
|
||||
/**
|
||||
* Set to true when user swipes to recents. In recents, we ignore the state of the recents
|
||||
* task list being frozen or not to allow the user to keep interacting with nav bar rotation
|
||||
* they went into recents with as opposed to defaulting to the default display rotation.
|
||||
* TODO: (b/156984037) For when user rotates after entering overview
|
||||
*/
|
||||
private boolean mInOverview;
|
||||
private boolean mTaskListFrozen;
|
||||
|
||||
private boolean mIsUserSetupComplete;
|
||||
|
||||
|
@ -186,6 +114,8 @@ public class RecentsAnimationDeviceState implements
|
|||
mDefaultDisplay = DefaultDisplay.INSTANCE.get(context);
|
||||
mDisplayId = mDefaultDisplay.getInfo().id;
|
||||
runOnDestroy(() -> mDefaultDisplay.removeChangeListener(this));
|
||||
mRotationTouchHelper = RotationTouchHelper.INSTANCE.get(context);
|
||||
runOnDestroy(mRotationTouchHelper::destroy);
|
||||
|
||||
// Register for user unlocked if necessary
|
||||
mIsUserUnlocked = context.getSystemService(UserManager.class)
|
||||
|
@ -207,10 +137,6 @@ public class RecentsAnimationDeviceState implements
|
|||
};
|
||||
runOnDestroy(mExclusionListener::unregister);
|
||||
|
||||
Resources resources = mContext.getResources();
|
||||
mOrientationTouchTransformer = new OrientationTouchTransformer(resources, mMode,
|
||||
() -> QuickStepContract.getWindowCornerRadius(resources));
|
||||
|
||||
// Register for navigation mode changes
|
||||
onNavigationModeChanged(mSysUiNavMode.addModeChangeListener(this));
|
||||
runOnDestroy(() -> mSysUiNavMode.removeModeChangeListener(this));
|
||||
|
@ -241,38 +167,6 @@ public class RecentsAnimationDeviceState implements
|
|||
userSetupObserver.register();
|
||||
runOnDestroy(userSetupObserver::unregister);
|
||||
}
|
||||
|
||||
mOrientationListener = new OrientationEventListener(context) {
|
||||
@Override
|
||||
public void onOrientationChanged(int degrees) {
|
||||
int newRotation = RecentsOrientedState.getRotationForUserDegreesRotated(degrees,
|
||||
mSensorRotation);
|
||||
if (newRotation == mSensorRotation) {
|
||||
return;
|
||||
}
|
||||
|
||||
mSensorRotation = newRotation;
|
||||
mPrioritizeDeviceRotation = true;
|
||||
|
||||
if (newRotation == mCurrentAppRotation) {
|
||||
// When user rotates device to the orientation of the foreground app after
|
||||
// quickstepping
|
||||
toggleSecondaryNavBarsForRotation();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void setupOrientationSwipeHandler() {
|
||||
ActivityManagerWrapper.getInstance().registerTaskStackListener(mFrozenTaskListener);
|
||||
mOnDestroyFrozenTaskRunnable = () -> ActivityManagerWrapper.getInstance()
|
||||
.unregisterTaskStackListener(mFrozenTaskListener);
|
||||
runOnDestroy(mOnDestroyFrozenTaskRunnable);
|
||||
}
|
||||
|
||||
private void destroyOrientationSwipeHandlerCallback() {
|
||||
ActivityManagerWrapper.getInstance().unregisterTaskStackListener(mFrozenTaskListener);
|
||||
mOnDestroyActions.remove(mOnDestroyFrozenTaskRunnable);
|
||||
}
|
||||
|
||||
private void runOnDestroy(Runnable action) {
|
||||
|
@ -311,13 +205,6 @@ public class RecentsAnimationDeviceState implements
|
|||
|
||||
mNavBarPosition = new NavBarPosition(newMode, mDefaultDisplay.getInfo());
|
||||
|
||||
mOrientationTouchTransformer.setNavigationMode(newMode, mDefaultDisplay.getInfo());
|
||||
if (!mMode.hasGestures && newMode.hasGestures) {
|
||||
setupOrientationSwipeHandler();
|
||||
} else if (mMode.hasGestures && !newMode.hasGestures){
|
||||
destroyOrientationSwipeHandlerCallback();
|
||||
}
|
||||
|
||||
mMode = newMode;
|
||||
}
|
||||
|
||||
|
@ -328,28 +215,10 @@ public class RecentsAnimationDeviceState implements
|
|||
return;
|
||||
}
|
||||
|
||||
mDisplayRotation = info.rotation;
|
||||
|
||||
if (!mMode.hasGestures) {
|
||||
return;
|
||||
}
|
||||
mNavBarPosition = new NavBarPosition(mMode, info);
|
||||
updateGestureTouchRegions();
|
||||
mOrientationTouchTransformer.createOrAddTouchRegion(info);
|
||||
mCurrentAppRotation = mDisplayRotation;
|
||||
|
||||
/* Update nav bars on the following:
|
||||
* a) if this is coming from an activity rotation OR
|
||||
* aa) we launch an app in the orientation that user is already in
|
||||
* b) We're not in overview, since overview will always be portrait (w/o home rotation)
|
||||
* c) We're actively in quickswitch mode
|
||||
*/
|
||||
if ((mPrioritizeDeviceRotation
|
||||
|| mCurrentAppRotation == mSensorRotation) // switch to an app of orientation user is in
|
||||
&& !mInOverview
|
||||
&& mTaskListFrozen) {
|
||||
toggleSecondaryNavBarsForRotation();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -464,7 +333,7 @@ public class RecentsAnimationDeviceState implements
|
|||
*/
|
||||
public boolean canStartSystemGesture() {
|
||||
boolean canStartWithNavHidden = (mSystemUiStateFlags & SYSUI_STATE_NAV_BAR_HIDDEN) == 0
|
||||
|| mTaskListFrozen;
|
||||
|| mRotationTouchHelper.isTaskListFrozen();
|
||||
return canStartWithNavHidden
|
||||
&& (mSystemUiStateFlags & SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED) == 0
|
||||
&& (mSystemUiStateFlags & SYSUI_STATE_QUICK_SETTINGS_EXPANDED) == 0
|
||||
|
@ -536,33 +405,6 @@ public class RecentsAnimationDeviceState implements
|
|||
return (mSystemUiStateFlags & SYSUI_STATE_OVERVIEW_DISABLED) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the regions for detecting the swipe up/quickswitch and assistant gestures.
|
||||
*/
|
||||
public void updateGestureTouchRegions() {
|
||||
if (!mMode.hasGestures) {
|
||||
return;
|
||||
}
|
||||
|
||||
mOrientationTouchTransformer.createOrAddTouchRegion(mDefaultDisplay.getInfo());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return whether the coordinates of the {@param event} is in the swipe up gesture region.
|
||||
*/
|
||||
public boolean isInSwipeUpTouchRegion(MotionEvent event) {
|
||||
return mOrientationTouchTransformer.touchInValidSwipeRegions(event.getX(), event.getY());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return whether the coordinates of the {@param event} with the given {@param pointerIndex}
|
||||
* is in the swipe up gesture region.
|
||||
*/
|
||||
public boolean isInSwipeUpTouchRegion(MotionEvent event, int pointerIndex) {
|
||||
return mOrientationTouchTransformer.touchInValidSwipeRegions(event.getX(pointerIndex),
|
||||
event.getY(pointerIndex));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the region in screen space where the gestures should be deferred (ie. due to specific
|
||||
* nav bar ui).
|
||||
|
@ -620,101 +462,13 @@ public class RecentsAnimationDeviceState implements
|
|||
public boolean canTriggerAssistantAction(MotionEvent ev, ActivityManager.RunningTaskInfo task) {
|
||||
return mAssistantAvailable
|
||||
&& !QuickStepContract.isAssistantGestureDisabled(mSystemUiStateFlags)
|
||||
&& mOrientationTouchTransformer.touchInAssistantRegion(ev)
|
||||
&& mRotationTouchHelper.touchInAssistantRegion(ev)
|
||||
&& !isLockToAppActive()
|
||||
&& !isGestureBlockedActivity(task);
|
||||
}
|
||||
|
||||
/**
|
||||
* *May* apply a transform on the motion event if it lies in the nav bar region for another
|
||||
* orientation that is currently being tracked as a part of quickstep
|
||||
*/
|
||||
void setOrientationTransformIfNeeded(MotionEvent event) {
|
||||
// negative coordinates bug b/143901881
|
||||
if (event.getX() < 0 || event.getY() < 0) {
|
||||
event.setLocation(Math.max(0, event.getX()), Math.max(0, event.getY()));
|
||||
}
|
||||
mOrientationTouchTransformer.transform(event);
|
||||
}
|
||||
|
||||
private void enableMultipleRegions(boolean enable) {
|
||||
mOrientationTouchTransformer.enableMultipleRegions(enable, mDefaultDisplay.getInfo());
|
||||
notifySysuiOfCurrentRotation(mOrientationTouchTransformer.getQuickStepStartingRotation());
|
||||
if (enable && !mInOverview && !TestProtocol.sDisableSensorRotation) {
|
||||
// Clear any previous state from sensor manager
|
||||
mSensorRotation = mCurrentAppRotation;
|
||||
mOrientationListener.enable();
|
||||
} else {
|
||||
mOrientationListener.disable();
|
||||
}
|
||||
}
|
||||
|
||||
public void onStartGesture() {
|
||||
if (mTaskListFrozen) {
|
||||
// Prioritize whatever nav bar user touches once in quickstep
|
||||
// This case is specifically when user changes what nav bar they are using mid
|
||||
// quickswitch session before tasks list is unfrozen
|
||||
notifySysuiOfCurrentRotation(mOrientationTouchTransformer.getCurrentActiveRotation());
|
||||
}
|
||||
}
|
||||
|
||||
void onEndTargetCalculated(GestureState.GestureEndTarget endTarget,
|
||||
BaseActivityInterface activityInterface) {
|
||||
if (endTarget == GestureState.GestureEndTarget.RECENTS) {
|
||||
mInOverview = true;
|
||||
if (!mTaskListFrozen) {
|
||||
// If we're in landscape w/o ever quickswitching, show the navbar in landscape
|
||||
enableMultipleRegions(true);
|
||||
}
|
||||
activityInterface.onExitOverview(this, mExitOverviewRunnable);
|
||||
} else if (endTarget == GestureState.GestureEndTarget.HOME) {
|
||||
enableMultipleRegions(false);
|
||||
} else if (endTarget == GestureState.GestureEndTarget.NEW_TASK) {
|
||||
if (mOrientationTouchTransformer.getQuickStepStartingRotation() == -1) {
|
||||
// First gesture to start quickswitch
|
||||
enableMultipleRegions(true);
|
||||
} else {
|
||||
notifySysuiOfCurrentRotation(
|
||||
mOrientationTouchTransformer.getCurrentActiveRotation());
|
||||
}
|
||||
|
||||
// A new gesture is starting, reset the current device rotation
|
||||
// This is done under the assumption that the user won't rotate the phone and then
|
||||
// quickswitch in the old orientation.
|
||||
mPrioritizeDeviceRotation = false;
|
||||
} else if (endTarget == GestureState.GestureEndTarget.LAST_TASK) {
|
||||
if (!mTaskListFrozen) {
|
||||
// touched nav bar but didn't go anywhere and not quickswitching, do nothing
|
||||
return;
|
||||
}
|
||||
notifySysuiOfCurrentRotation(mOrientationTouchTransformer.getCurrentActiveRotation());
|
||||
}
|
||||
}
|
||||
|
||||
private void notifySysuiOfCurrentRotation(int rotation) {
|
||||
UI_HELPER_EXECUTOR.execute(() -> SystemUiProxy.INSTANCE.get(mContext)
|
||||
.onQuickSwitchToNewTask(rotation));
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables/Enables multiple nav bars on {@link OrientationTouchTransformer} and then
|
||||
* notifies system UI of the primary rotation the user is interacting with
|
||||
*/
|
||||
private void toggleSecondaryNavBarsForRotation() {
|
||||
mOrientationTouchTransformer.setSingleActiveRegion(mDefaultDisplay.getInfo());
|
||||
notifySysuiOfCurrentRotation(mOrientationTouchTransformer.getCurrentActiveRotation());
|
||||
}
|
||||
|
||||
public int getCurrentActiveRotation() {
|
||||
if (!mMode.hasGestures) {
|
||||
// touch rotation should always match that of display for 3 button
|
||||
return mDisplayRotation;
|
||||
}
|
||||
return mOrientationTouchTransformer.getCurrentActiveRotation();
|
||||
}
|
||||
|
||||
public int getDisplayRotation() {
|
||||
return mDisplayRotation;
|
||||
public RotationTouchHelper getRotationTouchHelper() {
|
||||
return mRotationTouchHelper;
|
||||
}
|
||||
|
||||
public void dump(PrintWriter pw) {
|
||||
|
@ -726,9 +480,7 @@ public class RecentsAnimationDeviceState implements
|
|||
pw.println(" assistantAvailable=" + mAssistantAvailable);
|
||||
pw.println(" assistantDisabled="
|
||||
+ QuickStepContract.isAssistantGestureDisabled(mSystemUiStateFlags));
|
||||
pw.println(" currentActiveRotation=" + getCurrentActiveRotation());
|
||||
pw.println(" displayRotation=" + getDisplayRotation());
|
||||
pw.println(" isUserUnlocked=" + mIsUserUnlocked);
|
||||
mOrientationTouchTransformer.dump(pw);
|
||||
mRotationTouchHelper.dump(pw);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,15 +92,6 @@ public class RecentsModel extends TaskStackChangeListener {
|
|||
return mTaskList.getTasks(false /* loadKeysOnly */, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The task id of the running task, or -1 if there is no current running task.
|
||||
*/
|
||||
public static int getRunningTaskId() {
|
||||
ActivityManager.RunningTaskInfo runningTask =
|
||||
ActivityManagerWrapper.getInstance().getRunningTask();
|
||||
return runningTask != null ? runningTask.id : -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Whether the provided {@param changeId} is the latest recent tasks list id.
|
||||
*/
|
||||
|
@ -140,7 +131,9 @@ public class RecentsModel extends TaskStackChangeListener {
|
|||
}
|
||||
|
||||
// Keep the cache up to date with the latest thumbnails
|
||||
int runningTaskId = RecentsModel.getRunningTaskId();
|
||||
ActivityManager.RunningTaskInfo runningTask =
|
||||
ActivityManagerWrapper.getInstance().getRunningTask();
|
||||
int runningTaskId = runningTask != null ? runningTask.id : -1;
|
||||
mTaskList.getTaskKeys(mThumbnailCache.getCacheSize(), tasks -> {
|
||||
for (Task task : tasks) {
|
||||
if (task.key.id == runningTaskId) {
|
||||
|
|
|
@ -0,0 +1,365 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
import static android.view.Surface.ROTATION_0;
|
||||
|
||||
import static com.android.launcher3.util.DefaultDisplay.CHANGE_ALL;
|
||||
import static com.android.launcher3.util.DefaultDisplay.CHANGE_FRAME_DELAY;
|
||||
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
|
||||
import static com.android.quickstep.SysUINavigationMode.Mode.THREE_BUTTONS;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.OrientationEventListener;
|
||||
|
||||
import com.android.launcher3.testing.TestProtocol;
|
||||
import com.android.launcher3.util.DefaultDisplay;
|
||||
import com.android.launcher3.util.MainThreadInitializedObject;
|
||||
import com.android.quickstep.util.RecentsOrientedState;
|
||||
import com.android.systemui.shared.system.ActivityManagerWrapper;
|
||||
import com.android.systemui.shared.system.QuickStepContract;
|
||||
import com.android.systemui.shared.system.TaskStackChangeListener;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class RotationTouchHelper implements
|
||||
SysUINavigationMode.NavigationModeChangeListener,
|
||||
DefaultDisplay.DisplayInfoChangeListener {
|
||||
public static final MainThreadInitializedObject<RotationTouchHelper> INSTANCE =
|
||||
new MainThreadInitializedObject<>(RotationTouchHelper::new);
|
||||
|
||||
private final OrientationTouchTransformer mOrientationTouchTransformer;
|
||||
private final DefaultDisplay mDefaultDisplay;
|
||||
private final SysUINavigationMode mSysUiNavMode;
|
||||
private final int mDisplayId;
|
||||
private int mDisplayRotation;
|
||||
|
||||
private final ArrayList<Runnable> mOnDestroyActions = new ArrayList<>();
|
||||
|
||||
private SysUINavigationMode.Mode mMode = THREE_BUTTONS;
|
||||
|
||||
private TaskStackChangeListener mFrozenTaskListener = new TaskStackChangeListener() {
|
||||
@Override
|
||||
public void onRecentTaskListFrozenChanged(boolean frozen) {
|
||||
mTaskListFrozen = frozen;
|
||||
if (frozen || mInOverview) {
|
||||
return;
|
||||
}
|
||||
enableMultipleRegions(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityRotation(int displayId) {
|
||||
super.onActivityRotation(displayId);
|
||||
// This always gets called before onDisplayInfoChanged() so we know how to process
|
||||
// the rotation in that method. This is done to avoid having a race condition between
|
||||
// the sensor readings and onDisplayInfoChanged() call
|
||||
if (displayId != mDisplayId) {
|
||||
return;
|
||||
}
|
||||
|
||||
mPrioritizeDeviceRotation = true;
|
||||
if (mInOverview) {
|
||||
// reset, launcher must be rotating
|
||||
mExitOverviewRunnable.run();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private Runnable mExitOverviewRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mInOverview = false;
|
||||
enableMultipleRegions(false);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Used to listen for when the device rotates into the orientation of the current foreground
|
||||
* app. For example, if a user quickswitches from a portrait to a fixed landscape app and then
|
||||
* rotates rotates the device to match that orientation, this triggers calls to sysui to adjust
|
||||
* the navbar.
|
||||
*/
|
||||
private OrientationEventListener mOrientationListener;
|
||||
private int mSensorRotation = ROTATION_0;
|
||||
/**
|
||||
* This is the configuration of the foreground app or the app that will be in the foreground
|
||||
* once a quickstep gesture finishes.
|
||||
*/
|
||||
private int mCurrentAppRotation = -1;
|
||||
/**
|
||||
* This flag is set to true when the device physically changes orientations. When true, we will
|
||||
* always report the current rotation of the foreground app whenever the display changes, as it
|
||||
* would indicate the user's intention to rotate the foreground app.
|
||||
*/
|
||||
private boolean mPrioritizeDeviceRotation = false;
|
||||
private Runnable mOnDestroyFrozenTaskRunnable;
|
||||
/**
|
||||
* Set to true when user swipes to recents. In recents, we ignore the state of the recents
|
||||
* task list being frozen or not to allow the user to keep interacting with nav bar rotation
|
||||
* they went into recents with as opposed to defaulting to the default display rotation.
|
||||
* TODO: (b/156984037) For when user rotates after entering overview
|
||||
*/
|
||||
private boolean mInOverview;
|
||||
private boolean mTaskListFrozen;
|
||||
|
||||
|
||||
private final Context mContext;
|
||||
|
||||
private RotationTouchHelper(Context context) {
|
||||
mContext = context;
|
||||
Resources resources = mContext.getResources();
|
||||
mSysUiNavMode = SysUINavigationMode.INSTANCE.get(context);
|
||||
mDefaultDisplay = DefaultDisplay.INSTANCE.get(context);
|
||||
mDisplayId = mDefaultDisplay.getInfo().id;
|
||||
|
||||
mOrientationTouchTransformer = new OrientationTouchTransformer(resources, mMode,
|
||||
() -> QuickStepContract.getWindowCornerRadius(resources));
|
||||
|
||||
// Register for navigation mode changes
|
||||
onNavigationModeChanged(mSysUiNavMode.addModeChangeListener(this));
|
||||
runOnDestroy(() -> mSysUiNavMode.removeModeChangeListener(this));
|
||||
|
||||
mOrientationListener = new OrientationEventListener(context) {
|
||||
@Override
|
||||
public void onOrientationChanged(int degrees) {
|
||||
int newRotation = RecentsOrientedState.getRotationForUserDegreesRotated(degrees,
|
||||
mSensorRotation);
|
||||
if (newRotation == mSensorRotation) {
|
||||
return;
|
||||
}
|
||||
|
||||
mSensorRotation = newRotation;
|
||||
mPrioritizeDeviceRotation = true;
|
||||
|
||||
if (newRotation == mCurrentAppRotation) {
|
||||
// When user rotates device to the orientation of the foreground app after
|
||||
// quickstepping
|
||||
toggleSecondaryNavBarsForRotation();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void setupOrientationSwipeHandler() {
|
||||
ActivityManagerWrapper.getInstance().registerTaskStackListener(mFrozenTaskListener);
|
||||
mOnDestroyFrozenTaskRunnable = () -> ActivityManagerWrapper.getInstance()
|
||||
.unregisterTaskStackListener(mFrozenTaskListener);
|
||||
runOnDestroy(mOnDestroyFrozenTaskRunnable);
|
||||
}
|
||||
|
||||
private void destroyOrientationSwipeHandlerCallback() {
|
||||
ActivityManagerWrapper.getInstance().unregisterTaskStackListener(mFrozenTaskListener);
|
||||
mOnDestroyActions.remove(mOnDestroyFrozenTaskRunnable);
|
||||
}
|
||||
|
||||
private void runOnDestroy(Runnable action) {
|
||||
mOnDestroyActions.add(action);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans up all the registered listeners and receivers.
|
||||
*/
|
||||
public void destroy() {
|
||||
for (Runnable r : mOnDestroyActions) {
|
||||
r.run();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isTaskListFrozen() {
|
||||
return mTaskListFrozen;
|
||||
}
|
||||
|
||||
public boolean touchInAssistantRegion(MotionEvent ev) {
|
||||
return mOrientationTouchTransformer.touchInAssistantRegion(ev);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the regions for detecting the swipe up/quickswitch and assistant gestures.
|
||||
*/
|
||||
public void updateGestureTouchRegions() {
|
||||
if (!mMode.hasGestures) {
|
||||
return;
|
||||
}
|
||||
|
||||
mOrientationTouchTransformer.createOrAddTouchRegion(mDefaultDisplay.getInfo());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return whether the coordinates of the {@param event} is in the swipe up gesture region.
|
||||
*/
|
||||
public boolean isInSwipeUpTouchRegion(MotionEvent event) {
|
||||
return mOrientationTouchTransformer.touchInValidSwipeRegions(event.getX(), event.getY());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return whether the coordinates of the {@param event} with the given {@param pointerIndex}
|
||||
* is in the swipe up gesture region.
|
||||
*/
|
||||
public boolean isInSwipeUpTouchRegion(MotionEvent event, int pointerIndex) {
|
||||
return mOrientationTouchTransformer.touchInValidSwipeRegions(event.getX(pointerIndex),
|
||||
event.getY(pointerIndex));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onNavigationModeChanged(SysUINavigationMode.Mode newMode) {
|
||||
mDefaultDisplay.removeChangeListener(this);
|
||||
mDefaultDisplay.addChangeListener(this);
|
||||
onDisplayInfoChanged(mDefaultDisplay.getInfo(), CHANGE_ALL);
|
||||
|
||||
mOrientationTouchTransformer.setNavigationMode(newMode, mDefaultDisplay.getInfo());
|
||||
if (!mMode.hasGestures && newMode.hasGestures) {
|
||||
setupOrientationSwipeHandler();
|
||||
} else if (mMode.hasGestures && !newMode.hasGestures){
|
||||
destroyOrientationSwipeHandlerCallback();
|
||||
}
|
||||
|
||||
mMode = newMode;
|
||||
}
|
||||
|
||||
public int getDisplayRotation() {
|
||||
return mDisplayRotation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisplayInfoChanged(DefaultDisplay.Info info, int flags) {
|
||||
if (info.id != mDisplayId|| flags == CHANGE_FRAME_DELAY) {
|
||||
// ignore displays that aren't running launcher and frame refresh rate changes
|
||||
return;
|
||||
}
|
||||
|
||||
mDisplayRotation = info.rotation;
|
||||
|
||||
if (!mMode.hasGestures) {
|
||||
return;
|
||||
}
|
||||
updateGestureTouchRegions();
|
||||
mOrientationTouchTransformer.createOrAddTouchRegion(info);
|
||||
mCurrentAppRotation = mDisplayRotation;
|
||||
|
||||
/* Update nav bars on the following:
|
||||
* a) if this is coming from an activity rotation OR
|
||||
* aa) we launch an app in the orientation that user is already in
|
||||
* b) We're not in overview, since overview will always be portrait (w/o home rotation)
|
||||
* c) We're actively in quickswitch mode
|
||||
*/
|
||||
if ((mPrioritizeDeviceRotation
|
||||
|| mCurrentAppRotation == mSensorRotation) // switch to an app of orientation user is in
|
||||
&& !mInOverview
|
||||
&& mTaskListFrozen) {
|
||||
toggleSecondaryNavBarsForRotation();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* *May* apply a transform on the motion event if it lies in the nav bar region for another
|
||||
* orientation that is currently being tracked as a part of quickstep
|
||||
*/
|
||||
void setOrientationTransformIfNeeded(MotionEvent event) {
|
||||
// negative coordinates bug b/143901881
|
||||
if (event.getX() < 0 || event.getY() < 0) {
|
||||
event.setLocation(Math.max(0, event.getX()), Math.max(0, event.getY()));
|
||||
}
|
||||
mOrientationTouchTransformer.transform(event);
|
||||
}
|
||||
|
||||
private void enableMultipleRegions(boolean enable) {
|
||||
mOrientationTouchTransformer.enableMultipleRegions(enable, mDefaultDisplay.getInfo());
|
||||
notifySysuiOfCurrentRotation(mOrientationTouchTransformer.getQuickStepStartingRotation());
|
||||
if (enable && !mInOverview && !TestProtocol.sDisableSensorRotation) {
|
||||
// Clear any previous state from sensor manager
|
||||
mSensorRotation = mCurrentAppRotation;
|
||||
mOrientationListener.enable();
|
||||
} else {
|
||||
mOrientationListener.disable();
|
||||
}
|
||||
}
|
||||
|
||||
public void onStartGesture() {
|
||||
if (mTaskListFrozen) {
|
||||
// Prioritize whatever nav bar user touches once in quickstep
|
||||
// This case is specifically when user changes what nav bar they are using mid
|
||||
// quickswitch session before tasks list is unfrozen
|
||||
notifySysuiOfCurrentRotation(mOrientationTouchTransformer.getCurrentActiveRotation());
|
||||
}
|
||||
}
|
||||
|
||||
void onEndTargetCalculated(GestureState.GestureEndTarget endTarget,
|
||||
BaseActivityInterface activityInterface) {
|
||||
if (endTarget == GestureState.GestureEndTarget.RECENTS) {
|
||||
mInOverview = true;
|
||||
if (!mTaskListFrozen) {
|
||||
// If we're in landscape w/o ever quickswitching, show the navbar in landscape
|
||||
enableMultipleRegions(true);
|
||||
}
|
||||
activityInterface.onExitOverview(this, mExitOverviewRunnable);
|
||||
} else if (endTarget == GestureState.GestureEndTarget.HOME) {
|
||||
enableMultipleRegions(false);
|
||||
} else if (endTarget == GestureState.GestureEndTarget.NEW_TASK) {
|
||||
if (mOrientationTouchTransformer.getQuickStepStartingRotation() == -1) {
|
||||
// First gesture to start quickswitch
|
||||
enableMultipleRegions(true);
|
||||
} else {
|
||||
notifySysuiOfCurrentRotation(
|
||||
mOrientationTouchTransformer.getCurrentActiveRotation());
|
||||
}
|
||||
|
||||
// A new gesture is starting, reset the current device rotation
|
||||
// This is done under the assumption that the user won't rotate the phone and then
|
||||
// quickswitch in the old orientation.
|
||||
mPrioritizeDeviceRotation = false;
|
||||
} else if (endTarget == GestureState.GestureEndTarget.LAST_TASK) {
|
||||
if (!mTaskListFrozen) {
|
||||
// touched nav bar but didn't go anywhere and not quickswitching, do nothing
|
||||
return;
|
||||
}
|
||||
notifySysuiOfCurrentRotation(mOrientationTouchTransformer.getCurrentActiveRotation());
|
||||
}
|
||||
}
|
||||
|
||||
private void notifySysuiOfCurrentRotation(int rotation) {
|
||||
UI_HELPER_EXECUTOR.execute(() -> SystemUiProxy.INSTANCE.get(mContext)
|
||||
.onQuickSwitchToNewTask(rotation));
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables/Enables multiple nav bars on {@link OrientationTouchTransformer} and then
|
||||
* notifies system UI of the primary rotation the user is interacting with
|
||||
*/
|
||||
private void toggleSecondaryNavBarsForRotation() {
|
||||
mOrientationTouchTransformer.setSingleActiveRegion(mDefaultDisplay.getInfo());
|
||||
notifySysuiOfCurrentRotation(mOrientationTouchTransformer.getCurrentActiveRotation());
|
||||
}
|
||||
|
||||
public int getCurrentActiveRotation() {
|
||||
if (!mMode.hasGestures) {
|
||||
// touch rotation should always match that of display for 3 button
|
||||
return mDisplayRotation;
|
||||
}
|
||||
return mOrientationTouchTransformer.getCurrentActiveRotation();
|
||||
}
|
||||
|
||||
public void dump(PrintWriter pw) {
|
||||
pw.println("RotationTouchHelper:");
|
||||
pw.println(" currentActiveRotation=" + getCurrentActiveRotation());
|
||||
pw.println(" displayRotation=" + getDisplayRotation());
|
||||
mOrientationTouchTransformer.dump(pw);
|
||||
}
|
||||
}
|
|
@ -17,6 +17,7 @@ package com.android.quickstep.interaction;
|
|||
|
||||
import static com.android.launcher3.anim.Interpolators.ACCEL;
|
||||
import static com.android.launcher3.util.DefaultDisplay.getSingleFrameMs;
|
||||
import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATION;
|
||||
import static com.android.quickstep.BaseSwipeUpHandlerV2.MAX_SWIPE_DURATION;
|
||||
import static com.android.quickstep.interaction.TutorialController.TutorialType.HOME_NAVIGATION_COMPLETE;
|
||||
import static com.android.quickstep.interaction.TutorialController.TutorialType.OVERVIEW_NAVIGATION_COMPLETE;
|
||||
|
@ -110,6 +111,7 @@ abstract class SwipeUpGestureTutorialController extends TutorialController {
|
|||
AnimatorListenerAdapter resetTaskView = new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation, boolean isReverse) {
|
||||
mFakeIconView.setVisibility(View.INVISIBLE);
|
||||
mFakeTaskView.setVisibility(View.INVISIBLE);
|
||||
mFakeTaskView.setAlpha(1);
|
||||
mRunningWindowAnim = null;
|
||||
|
@ -131,6 +133,7 @@ abstract class SwipeUpGestureTutorialController extends TutorialController {
|
|||
});
|
||||
} else {
|
||||
anim.setViewAlpha(mFakeTaskView, 0, ACCEL);
|
||||
anim.setViewAlpha(mFakeIconView, 0, ACCEL);
|
||||
anim.addListener(resetTaskView);
|
||||
}
|
||||
if (onEndRunnable != null) {
|
||||
|
@ -202,7 +205,7 @@ abstract class SwipeUpGestureTutorialController extends TutorialController {
|
|||
// derivative of the scroll interpolator at zero, ie. 2.
|
||||
long baseDuration = Math.round(Math.abs(distanceToTravel / velocityPxPerMs.y));
|
||||
long duration = Math.min(MAX_SWIPE_DURATION, 2 * baseDuration);
|
||||
HomeAnimationFactory homeAnimFactory = new HomeAnimationFactory(null) {
|
||||
HomeAnimationFactory homeAnimFactory = new HomeAnimationFactory() {
|
||||
@Override
|
||||
public AnimatorPlaybackController createActivityAnimationToHome() {
|
||||
return AnimatorPlaybackController.wrap(new AnimatorSet(), duration);
|
||||
|
@ -218,6 +221,24 @@ abstract class SwipeUpGestureTutorialController extends TutorialController {
|
|||
fakeHomeIconLeft + fakeHomeIconSizePx,
|
||||
fakeHomeIconTop + fakeHomeIconSizePx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(RectF rect, float progress, float radius) {
|
||||
mFakeIconView.setVisibility(View.VISIBLE);
|
||||
mFakeIconView.update(rect, progress,
|
||||
1f - SHAPE_PROGRESS_DURATION /* shapeProgressStart */,
|
||||
radius,
|
||||
false, /* isOpening */
|
||||
mFakeIconView, mDp,
|
||||
false /* isVerticalBarLayout */);
|
||||
mFakeIconView.setAlpha(1);
|
||||
mFakeTaskView.setAlpha(getWindowAlpha(progress));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel() {
|
||||
mFakeIconView.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
};
|
||||
RectFSpringAnim windowAnim = createWindowAnimationToHome(startShift, homeAnimFactory);
|
||||
windowAnim.start(mContext, velocityPxPerMs);
|
||||
|
|
|
@ -28,6 +28,7 @@ import androidx.annotation.CallSuper;
|
|||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.views.ClipIconView;
|
||||
import com.android.quickstep.interaction.EdgeBackGestureHandler.BackGestureAttemptCallback;
|
||||
import com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestureAttemptCallback;
|
||||
|
||||
|
@ -46,6 +47,7 @@ abstract class TutorialController implements BackGestureAttemptCallback,
|
|||
final TextView mTitleTextView;
|
||||
final TextView mSubtitleTextView;
|
||||
final TextView mFeedbackView;
|
||||
final ClipIconView mFakeIconView;
|
||||
final View mFakeTaskView;
|
||||
final View mRippleView;
|
||||
final RippleDrawable mRippleDrawable;
|
||||
|
@ -66,6 +68,7 @@ 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);
|
||||
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);
|
||||
mRippleDrawable = (RippleDrawable) mRippleView.getBackground();
|
||||
|
|
|
@ -27,7 +27,7 @@ import static com.android.systemui.shared.system.SysUiStatsLog.LAUNCHER_UICHANGE
|
|||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.WorkerThread;
|
||||
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.Utilities;
|
||||
|
@ -54,6 +54,7 @@ import com.android.systemui.shared.system.SysUiStatsLog;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Optional;
|
||||
import java.util.OptionalInt;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
/**
|
||||
* This class calls StatsLog compile time generated methods.
|
||||
|
@ -68,8 +69,6 @@ public class StatsLogCompatManager extends StatsLogManager {
|
|||
private static final String TAG = "StatsLog";
|
||||
private static final boolean IS_VERBOSE = Utilities.isPropertyEnabled(LogConfig.STATSLOG);
|
||||
|
||||
private static Context sContext;
|
||||
|
||||
private static final InstanceId DEFAULT_INSTANCE_ID = InstanceId.fakeInstanceId(0);
|
||||
// LauncherAtom.ItemInfo.getDefaultInstance() should be used but until launcher proto migrates
|
||||
// from nano to lite, bake constant to prevent robo test failure.
|
||||
|
@ -77,8 +76,13 @@ public class StatsLogCompatManager extends StatsLogManager {
|
|||
private static final int FOLDER_HIERARCHY_OFFSET = 100;
|
||||
private static final int SEARCH_RESULT_HIERARCHY_OFFSET = 200;
|
||||
|
||||
public static final CopyOnWriteArrayList<StatsLogConsumer> LOGS_CONSUMER =
|
||||
new CopyOnWriteArrayList<>();
|
||||
|
||||
private final Context mContext;
|
||||
|
||||
public StatsLogCompatManager(Context context) {
|
||||
sContext = context;
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -86,25 +90,12 @@ public class StatsLogCompatManager extends StatsLogManager {
|
|||
return new StatsCompatLogger();
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a ranking event and accompanying {@link InstanceId} and package name.
|
||||
*/
|
||||
@Override
|
||||
public void log(EventEnum rankingEvent, InstanceId instanceId, @Nullable String packageName,
|
||||
int position) {
|
||||
SysUiStatsLog.write(SysUiStatsLog.RANKING_SELECTED,
|
||||
rankingEvent.getId() /* event_id = 1; */,
|
||||
packageName /* package_name = 2; */,
|
||||
instanceId.getId() /* instance_id = 3; */,
|
||||
position /* position_picked = 4; */);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs the workspace layout information on the model thread.
|
||||
*/
|
||||
@Override
|
||||
public void logSnapshot() {
|
||||
LauncherAppState.getInstance(sContext).getModel().enqueueModelUpdateTask(
|
||||
LauncherAppState.getInstance(mContext).getModel().enqueueModelUpdateTask(
|
||||
new SnapshotWorker());
|
||||
}
|
||||
|
||||
|
@ -175,6 +166,7 @@ public class StatsLogCompatManager extends StatsLogManager {
|
|||
private static class StatsCompatLogger implements StatsLogger {
|
||||
|
||||
private static final ItemInfo DEFAULT_ITEM_INFO = new ItemInfo();
|
||||
|
||||
private ItemInfo mItemInfo = DEFAULT_ITEM_INFO;
|
||||
private InstanceId mInstanceId = DEFAULT_INSTANCE_ID;
|
||||
private OptionalInt mRank = OptionalInt.empty();
|
||||
|
@ -253,36 +245,35 @@ public class StatsLogCompatManager extends StatsLogManager {
|
|||
return;
|
||||
}
|
||||
|
||||
if (mItemInfo.container < 0) {
|
||||
// Item is not within a folder. Write to StatsLog in same thread.
|
||||
write(event, mInstanceId, applyOverwrites(mItemInfo.buildProto()), mSrcState,
|
||||
mDstState);
|
||||
LauncherAppState appState = LauncherAppState.getInstanceNoCreate();
|
||||
if (mItemInfo.container < 0 || appState == null) {
|
||||
// Write log on the model thread so that logs do not go out of order
|
||||
// (for eg: drop comes after drag)
|
||||
Executors.MODEL_EXECUTOR.execute(
|
||||
() -> write(event, applyOverwrites(mItemInfo.buildProto())));
|
||||
} else {
|
||||
// Item is inside the folder, fetch folder info in a BG thread
|
||||
// and then write to StatsLog.
|
||||
LauncherAppState.getInstance(sContext).getModel().enqueueModelUpdateTask(
|
||||
appState.getModel().enqueueModelUpdateTask(
|
||||
new BaseModelUpdateTask() {
|
||||
@Override
|
||||
public void execute(LauncherAppState app, BgDataModel dataModel,
|
||||
AllAppsList apps) {
|
||||
FolderInfo folderInfo = dataModel.folders.get(mItemInfo.container);
|
||||
write(event, mInstanceId,
|
||||
applyOverwrites(mItemInfo.buildProto(folderInfo)),
|
||||
mSrcState, mDstState);
|
||||
write(event, applyOverwrites(mItemInfo.buildProto(folderInfo)));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private LauncherAtom.ItemInfo applyOverwrites(LauncherAtom.ItemInfo atomInfo) {
|
||||
LauncherAtom.ItemInfo.Builder itemInfoBuilder =
|
||||
(LauncherAtom.ItemInfo.Builder) atomInfo.toBuilder();
|
||||
LauncherAtom.ItemInfo.Builder itemInfoBuilder = atomInfo.toBuilder();
|
||||
|
||||
mRank.ifPresent(itemInfoBuilder::setRank);
|
||||
mContainerInfo.ifPresent(itemInfoBuilder::setContainerInfo);
|
||||
|
||||
if (mFromState.isPresent() || mToState.isPresent() || mEditText.isPresent()) {
|
||||
FolderIcon.Builder folderIconBuilder = (FolderIcon.Builder) itemInfoBuilder
|
||||
FolderIcon.Builder folderIconBuilder = itemInfoBuilder
|
||||
.getFolderIcon()
|
||||
.toBuilder();
|
||||
mFromState.ifPresent(folderIconBuilder::setFromLabelState);
|
||||
|
@ -293,8 +284,11 @@ public class StatsLogCompatManager extends StatsLogManager {
|
|||
return itemInfoBuilder.build();
|
||||
}
|
||||
|
||||
private void write(EventEnum event, InstanceId instanceId, LauncherAtom.ItemInfo atomInfo,
|
||||
int srcState, int dstState) {
|
||||
@WorkerThread
|
||||
private void write(EventEnum event, LauncherAtom.ItemInfo atomInfo) {
|
||||
InstanceId instanceId = mInstanceId;
|
||||
int srcState = mSrcState;
|
||||
int dstState = mDstState;
|
||||
if (IS_VERBOSE) {
|
||||
String name = (event instanceof Enum) ? ((Enum) event).name() :
|
||||
event.getId() + "";
|
||||
|
@ -307,6 +301,10 @@ public class StatsLogCompatManager extends StatsLogManager {
|
|||
atomInfo));
|
||||
}
|
||||
|
||||
for (StatsLogConsumer consumer : LOGS_CONSUMER) {
|
||||
consumer.consume(event, atomInfo);
|
||||
}
|
||||
|
||||
SysUiStatsLog.write(
|
||||
SysUiStatsLog.LAUNCHER_EVENT,
|
||||
SysUiStatsLog.LAUNCHER_UICHANGED__ACTION__DEFAULT_ACTION /* deprecated */,
|
||||
|
@ -446,7 +444,16 @@ public class StatsLogCompatManager extends StatsLogManager {
|
|||
return "ALLAPPS";
|
||||
default:
|
||||
return "INVALID";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface to get stats log while it is dispatched to the system
|
||||
*/
|
||||
public interface StatsLogConsumer {
|
||||
|
||||
@WorkerThread
|
||||
void consume(EventEnum event, LauncherAtom.ItemInfo atomInfo);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ public class LayoutUtils {
|
|||
Rect taskSize = new Rect();
|
||||
LauncherActivityInterface.INSTANCE.calculateTaskSize(context, dp, taskSize,
|
||||
orientationHandler);
|
||||
return (dp.heightPx - taskSize.height()) / 2;
|
||||
return orientationHandler.getDistanceToBottomOfRect(dp, taskSize);
|
||||
}
|
||||
int shelfHeight = dp.hotseatBarSizePx + dp.getInsets().bottom;
|
||||
int spaceBetweenShelfAndRecents = (int) context.getResources().getDimension(
|
||||
|
|
|
@ -17,7 +17,8 @@
|
|||
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="match_parent">
|
||||
android:layout_height="match_parent"
|
||||
android:focusable="false">
|
||||
|
||||
<com.android.launcher3.CellLayout
|
||||
android:id="@+id/workspace"
|
||||
|
|
|
@ -142,7 +142,7 @@
|
|||
|
||||
<item name="staggered_damping_ratio" type="dimen" format="float">0.7</item>
|
||||
<item name="staggered_stiffness" type="dimen" format="float">150</item>
|
||||
<dimen name="unlock_staggered_velocity_dp_per_s">3dp</dimen>
|
||||
<dimen name="unlock_staggered_velocity_dp_per_s">4dp</dimen>
|
||||
|
||||
<item name="hint_scale_damping_ratio" type="dimen" format="float">0.7</item>
|
||||
<item name="hint_scale_stiffness" type="dimen" format="float">200</item>
|
||||
|
|
|
@ -45,7 +45,6 @@ import androidx.annotation.Nullable;
|
|||
import com.android.launcher3.LauncherSettings.Favorites;
|
||||
import com.android.launcher3.logging.InstanceId;
|
||||
import com.android.launcher3.logging.InstanceIdSequence;
|
||||
import com.android.launcher3.model.AppLaunchTracker;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.touch.ItemClickHandler;
|
||||
|
@ -82,7 +81,7 @@ public abstract class BaseDraggingActivity extends BaseActivity
|
|||
super.onCreate(savedInstanceState);
|
||||
|
||||
|
||||
mIsSafeModeEnabled = TraceHelper.whitelistIpcs("isSafeMode",
|
||||
mIsSafeModeEnabled = TraceHelper.allowIpcs("isSafeMode",
|
||||
() -> getPackageManager().isSafeMode());
|
||||
DefaultDisplay.INSTANCE.get(this).addChangeListener(this);
|
||||
|
||||
|
@ -154,8 +153,7 @@ public abstract class BaseDraggingActivity extends BaseActivity
|
|||
|
||||
public abstract ActivityOptions getActivityLaunchOptions(View v);
|
||||
|
||||
public boolean startActivitySafely(View v, Intent intent, @Nullable ItemInfo item,
|
||||
@Nullable String sourceContainer) {
|
||||
public boolean startActivitySafely(View v, Intent intent, @Nullable ItemInfo item) {
|
||||
if (mIsSafeModeEnabled && !PackageManagerHelper.isSystemApp(this, intent)) {
|
||||
Toast.makeText(this, R.string.safemode_shortcut_error, Toast.LENGTH_SHORT).show();
|
||||
return false;
|
||||
|
@ -176,17 +174,13 @@ public abstract class BaseDraggingActivity extends BaseActivity
|
|||
&& !((WorkspaceItemInfo) item).isPromise();
|
||||
if (isShortcut) {
|
||||
// Shortcuts need some special checks due to legacy reasons.
|
||||
startShortcutIntentSafely(intent, optsBundle, item, sourceContainer);
|
||||
startShortcutIntentSafely(intent, optsBundle, item);
|
||||
} else if (user == null || user.equals(Process.myUserHandle())) {
|
||||
// Could be launching some bookkeeping activity
|
||||
startActivity(intent, optsBundle);
|
||||
AppLaunchTracker.INSTANCE.get(this).onStartApp(intent.getComponent(),
|
||||
Process.myUserHandle(), sourceContainer);
|
||||
} else {
|
||||
getSystemService(LauncherApps.class).startMainActivity(
|
||||
intent.getComponent(), user, intent.getSourceBounds(), optsBundle);
|
||||
AppLaunchTracker.INSTANCE.get(this).onStartApp(intent.getComponent(), user,
|
||||
sourceContainer);
|
||||
}
|
||||
getUserEventDispatcher().logAppLaunch(v, intent, user);
|
||||
if (item != null) {
|
||||
|
@ -206,8 +200,7 @@ public abstract class BaseDraggingActivity extends BaseActivity
|
|||
.log(LAUNCHER_APP_LAUNCH_TAP);
|
||||
}
|
||||
|
||||
private void startShortcutIntentSafely(Intent intent, Bundle optsBundle, ItemInfo info,
|
||||
@Nullable String sourceContainer) {
|
||||
private void startShortcutIntentSafely(Intent intent, Bundle optsBundle, ItemInfo info) {
|
||||
try {
|
||||
StrictMode.VmPolicy oldPolicy = StrictMode.getVmPolicy();
|
||||
try {
|
||||
|
@ -221,8 +214,6 @@ public abstract class BaseDraggingActivity extends BaseActivity
|
|||
String id = ((WorkspaceItemInfo) info).getDeepShortcutId();
|
||||
String packageName = intent.getPackage();
|
||||
startShortcut(packageName, id, intent.getSourceBounds(), optsBundle, info.user);
|
||||
AppLaunchTracker.INSTANCE.get(this).onStartShortcut(packageName, id, info.user,
|
||||
sourceContainer);
|
||||
} else {
|
||||
// Could be launching some bookkeeping activity
|
||||
startActivity(intent, optsBundle);
|
||||
|
|
|
@ -183,6 +183,10 @@ public abstract class BaseRecyclerView extends RecyclerView {
|
|||
public void onScrollStateChanged(int state) {
|
||||
super.onScrollStateChanged(state);
|
||||
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
Log.d(TestProtocol.NO_SCROLL_END_WIDGETS, "onScrollStateChanged: " + state);
|
||||
}
|
||||
|
||||
if (state == SCROLL_STATE_IDLE) {
|
||||
AccessibilityManagerCompat.sendScrollFinishedEventToTest(getContext());
|
||||
}
|
||||
|
@ -192,6 +196,10 @@ public abstract class BaseRecyclerView extends RecyclerView {
|
|||
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
|
||||
super.onInitializeAccessibilityNodeInfo(info);
|
||||
if (isLayoutSuppressed()) info.setScrollable(false);
|
||||
if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
|
||||
Log.d(TestProtocol.NO_SCROLL_END_WIDGETS,
|
||||
"onInitializeAccessibilityNodeInfo, scrollable: " + info.isScrollable());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -199,8 +207,12 @@ public abstract class BaseRecyclerView extends RecyclerView {
|
|||
final boolean changing = frozen != isLayoutSuppressed();
|
||||
super.setLayoutFrozen(frozen);
|
||||
if (changing) {
|
||||
if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
|
||||
Log.d(TestProtocol.NO_SCROLL_END_WIDGETS, "setLayoutFrozen " + frozen
|
||||
+ " @ " + Log.getStackTraceString(new Throwable()));
|
||||
ActivityContext.lookupContext(getContext()).getDragLayer()
|
||||
.sendAccessibilityEvent(TYPE_WINDOW_CONTENT_CHANGED);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -331,10 +331,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
|||
public boolean onTouchEvent(MotionEvent event) {
|
||||
// ignore events if they happen in padding area
|
||||
if (event.getAction() == MotionEvent.ACTION_DOWN
|
||||
&& (event.getY() < getPaddingTop()
|
||||
|| event.getX() < getPaddingLeft()
|
||||
|| event.getY() > getHeight() - getPaddingBottom()
|
||||
|| event.getX() > getWidth() - getPaddingRight())) {
|
||||
&& shouldIgnoreTouchDown(event.getX(), event.getY())) {
|
||||
return false;
|
||||
}
|
||||
if (isLongClickable()) {
|
||||
|
@ -347,6 +344,16 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the touch down at the provided position be ignored
|
||||
*/
|
||||
protected boolean shouldIgnoreTouchDown(float x, float y) {
|
||||
return y < getPaddingTop()
|
||||
|| x < getPaddingLeft()
|
||||
|| y > getHeight() - getPaddingBottom()
|
||||
|| x > getWidth() - getPaddingRight();
|
||||
}
|
||||
|
||||
void setStayPressed(boolean stayPressed) {
|
||||
mStayPressed = stayPressed;
|
||||
refreshDrawableState();
|
||||
|
|
|
@ -814,7 +814,7 @@ public class Launcher extends StatefulActivity<LauncherState> implements Launche
|
|||
|
||||
if (grantResults.length > 0
|
||||
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
startActivitySafely(v, intent, null, null);
|
||||
startActivitySafely(v, intent, null);
|
||||
} else {
|
||||
// TODO: Show a snack bar with link to settings
|
||||
Toast.makeText(this, getString(R.string.msg_no_phone_permission,
|
||||
|
@ -923,6 +923,7 @@ public class Launcher extends StatefulActivity<LauncherState> implements Launche
|
|||
DiscoveryBounce.showForHomeIfNeeded(this);
|
||||
}
|
||||
|
||||
protected void handlePendingActivityRequest() { }
|
||||
|
||||
private void logStopAndResume(int command) {
|
||||
int pageIndex = mWorkspace.isOverlayShown() ? -1 : mWorkspace.getCurrentPage();
|
||||
|
@ -1423,7 +1424,8 @@ public class Launcher extends StatefulActivity<LauncherState> implements Launche
|
|||
if (!isInState(NORMAL)) {
|
||||
// Only change state, if not already the same. This prevents cancelling any
|
||||
// animations running as part of resume
|
||||
mStateManager.goToState(NORMAL);
|
||||
mStateManager.goToState(NORMAL, mStateManager.shouldAnimateStateChange(),
|
||||
this::handlePendingActivityRequest);
|
||||
}
|
||||
|
||||
// Reset the apps view
|
||||
|
@ -1860,13 +1862,12 @@ public class Launcher extends StatefulActivity<LauncherState> implements Launche
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean startActivitySafely(View v, Intent intent, ItemInfo item,
|
||||
@Nullable String sourceContainer) {
|
||||
public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
|
||||
if (!hasBeenResumed()) {
|
||||
// Workaround an issue where the WM launch animation is clobbered when finishing the
|
||||
// recents animation into launcher. Defer launching the activity until Launcher is
|
||||
// next resumed.
|
||||
addOnResumeCallback(() -> startActivitySafely(v, intent, item, sourceContainer));
|
||||
addOnResumeCallback(() -> startActivitySafely(v, intent, item));
|
||||
if (mOnDeferredActivityLaunchCallback != null) {
|
||||
mOnDeferredActivityLaunchCallback.run();
|
||||
mOnDeferredActivityLaunchCallback = null;
|
||||
|
@ -1874,7 +1875,7 @@ public class Launcher extends StatefulActivity<LauncherState> implements Launche
|
|||
return true;
|
||||
}
|
||||
|
||||
boolean success = super.startActivitySafely(v, intent, item, sourceContainer);
|
||||
boolean success = super.startActivitySafely(v, intent, item);
|
||||
if (success && v instanceof BubbleTextView) {
|
||||
// This is set to the view that launched the activity that navigated the user away
|
||||
// from launcher. Since there is no callback for when the activity has finished
|
||||
|
|
|
@ -58,7 +58,7 @@ import com.android.launcher3.pm.InstallSessionTracker;
|
|||
import com.android.launcher3.pm.PackageInstallInfo;
|
||||
import com.android.launcher3.pm.UserCache;
|
||||
import com.android.launcher3.shortcuts.ShortcutRequest;
|
||||
import com.android.launcher3.util.IntSparseArrayMap;
|
||||
import com.android.launcher3.util.IntSet;
|
||||
import com.android.launcher3.util.ItemInfoMatcher;
|
||||
import com.android.launcher3.util.LooperExecutor;
|
||||
import com.android.launcher3.util.PackageUserKey;
|
||||
|
@ -410,7 +410,7 @@ public class LauncherModel extends LauncherApps.Callback implements InstallSessi
|
|||
enqueueModelUpdateTask(new BaseModelUpdateTask() {
|
||||
@Override
|
||||
public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) {
|
||||
final IntSparseArrayMap<Boolean> removedIds = new IntSparseArrayMap<>();
|
||||
final IntSet removedIds = new IntSet();
|
||||
synchronized (dataModel) {
|
||||
for (ItemInfo info : dataModel.itemsIdMap) {
|
||||
if (info instanceof WorkspaceItemInfo
|
||||
|
@ -418,13 +418,13 @@ public class LauncherModel extends LauncherApps.Callback implements InstallSessi
|
|||
&& user.equals(info.user)
|
||||
&& info.getIntent() != null
|
||||
&& TextUtils.equals(packageName, info.getIntent().getPackage())) {
|
||||
removedIds.put(info.id, true /* remove */);
|
||||
removedIds.add(info.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!removedIds.isEmpty()) {
|
||||
deleteAndBindComponentsRemoved(ItemInfoMatcher.ofItemIds(removedIds, false));
|
||||
deleteAndBindComponentsRemoved(ItemInfoMatcher.ofItemIds(removedIds));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -250,7 +250,8 @@ public abstract class LauncherState implements BaseState<LauncherState> {
|
|||
}
|
||||
|
||||
public PageAlphaProvider getWorkspacePageAlphaProvider(Launcher launcher) {
|
||||
if (this != NORMAL || !launcher.getDeviceProfile().shouldFadeAdjacentWorkspaceScreens()) {
|
||||
if ((this != NORMAL && this != HINT_STATE)
|
||||
|| !launcher.getDeviceProfile().shouldFadeAdjacentWorkspaceScreens()) {
|
||||
return DEFAULT_ALPHA_PROVIDER;
|
||||
}
|
||||
final int centerPage = launcher.getWorkspace().getNextPage();
|
||||
|
|
|
@ -39,7 +39,7 @@ 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.model.AppLaunchTracker;
|
||||
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;
|
||||
|
@ -218,13 +218,16 @@ public class SecondaryDropTarget extends ButtonDropTarget implements OnAlarmList
|
|||
public void onDrop(DragObject d, DragOptions options) {
|
||||
// Defer onComplete
|
||||
d.dragSource = new DeferredOnComplete(d.dragSource, getContext());
|
||||
|
||||
super.onDrop(d, options);
|
||||
StatsLogger logger = mStatsLogManager.logger().withInstanceId(d.logInstanceId);
|
||||
if (d.originalDragInfo != null) {
|
||||
logger.withItemInfo(d.originalDragInfo);
|
||||
}
|
||||
if (mCurrentAccessibilityAction == UNINSTALL) {
|
||||
mStatsLogManager.logger().withInstanceId(d.logInstanceId)
|
||||
.log(LAUNCHER_ITEM_DROPPED_ON_UNINSTALL);
|
||||
logger.log(LAUNCHER_ITEM_DROPPED_ON_UNINSTALL);
|
||||
} else if (mCurrentAccessibilityAction == DISMISS_PREDICTION) {
|
||||
mStatsLogManager.logger().withInstanceId(d.logInstanceId)
|
||||
.log(LAUNCHER_ITEM_DROPPED_ON_DONT_SUGGEST);
|
||||
logger.log(LAUNCHER_ITEM_DROPPED_ON_DONT_SUGGEST);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -283,8 +286,7 @@ public class SecondaryDropTarget extends ButtonDropTarget implements OnAlarmList
|
|||
return null;
|
||||
}
|
||||
if (mCurrentAccessibilityAction == DISMISS_PREDICTION) {
|
||||
AppLaunchTracker.INSTANCE.get(getContext()).onDismissApp(info.getTargetComponent(),
|
||||
info.user, AppLaunchTracker.CONTAINER_PREDICTIONS);
|
||||
// We sent the log event, nothing else left to do
|
||||
return null;
|
||||
}
|
||||
// else: mCurrentAccessibilityAction == UNINSTALL
|
||||
|
|
|
@ -309,7 +309,9 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
|||
// In portrait, we want the pages spaced such that there is no
|
||||
// overhang of the previous / next page into the current page viewport.
|
||||
// We assume symmetrical padding in portrait mode.
|
||||
setPageSpacing(Math.max(grid.edgeMarginPx, padding.left + 1));
|
||||
int maxInsets = Math.max(insets.left, insets.right);
|
||||
int maxPadding = Math.max(grid.edgeMarginPx, padding.left + 1);
|
||||
setPageSpacing(Math.max(maxInsets, maxPadding));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -83,7 +83,7 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo
|
|||
protected final BaseDraggingActivity mLauncher;
|
||||
protected final AdapterHolder[] mAH;
|
||||
private final ItemInfoMatcher mPersonalMatcher = ItemInfoMatcher.ofUser(Process.myUserHandle());
|
||||
private final ItemInfoMatcher mWorkMatcher = ItemInfoMatcher.not(mPersonalMatcher);
|
||||
private final ItemInfoMatcher mWorkMatcher = mPersonalMatcher.negate();
|
||||
private final AllAppsStore mAllAppsStore = new AllAppsStore();
|
||||
|
||||
private final Paint mNavBarScrimPaint;
|
||||
|
|
|
@ -41,7 +41,6 @@ import com.android.launcher3.BaseDraggingActivity;
|
|||
import com.android.launcher3.BubbleTextView;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.allapps.AlphabeticalAppsList.AdapterItem;
|
||||
import com.android.launcher3.model.AppLaunchTracker;
|
||||
import com.android.launcher3.model.data.AppInfo;
|
||||
import com.android.launcher3.util.PackageManagerHelper;
|
||||
|
||||
|
@ -270,7 +269,7 @@ public class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter.
|
|||
View searchMarketView = mLayoutInflater.inflate(R.layout.all_apps_search_market,
|
||||
parent, false);
|
||||
searchMarketView.setOnClickListener(v -> mLauncher.startActivitySafely(
|
||||
v, mMarketSearchIntent, null, AppLaunchTracker.CONTAINER_SEARCH));
|
||||
v, mMarketSearchIntent, null));
|
||||
return new ViewHolder(searchMarketView);
|
||||
case VIEW_TYPE_ALL_APPS_DIVIDER:
|
||||
return new ViewHolder(mLayoutInflater.inflate(
|
||||
|
|
|
@ -28,7 +28,6 @@ import android.widget.TextView.OnEditorActionListener;
|
|||
import com.android.launcher3.BaseDraggingActivity;
|
||||
import com.android.launcher3.ExtendedEditText;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.model.AppLaunchTracker;
|
||||
import com.android.launcher3.util.ComponentKey;
|
||||
import com.android.launcher3.util.PackageManagerHelper;
|
||||
|
||||
|
@ -112,8 +111,8 @@ public class AllAppsSearchBarController
|
|||
return false;
|
||||
}
|
||||
return mLauncher.startActivitySafely(v,
|
||||
PackageManagerHelper.getMarketSearchIntent(mLauncher, query), null,
|
||||
AppLaunchTracker.CONTAINER_SEARCH);
|
||||
PackageManagerHelper.getMarketSearchIntent(mLauncher, query), null
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -75,6 +75,9 @@ public class AccessibilityManagerCompat {
|
|||
}
|
||||
|
||||
public static void sendScrollFinishedEventToTest(Context context) {
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
Log.d(TestProtocol.NO_SCROLL_END_WIDGETS, "sendScrollFinishedEventToTest");
|
||||
}
|
||||
final AccessibilityManager accessibilityManager = getAccessibilityManagerForTest(context);
|
||||
if (accessibilityManager == null) return;
|
||||
|
||||
|
@ -94,6 +97,9 @@ public class AccessibilityManagerCompat {
|
|||
AccessibilityEvent.TYPE_ANNOUNCEMENT);
|
||||
e.setClassName(eventTag);
|
||||
e.setParcelableData(data);
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
Log.d(TestProtocol.NO_SCROLL_END_WIDGETS, "sendEventToTest " + e);
|
||||
}
|
||||
accessibilityManager.sendAccessibilityEvent(e);
|
||||
}
|
||||
|
||||
|
|
|
@ -241,9 +241,9 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
|
|||
mFolderName.setSelectAllOnFocus(true);
|
||||
mFolderName.setInputType(mFolderName.getInputType()
|
||||
& ~InputType.TYPE_TEXT_FLAG_AUTO_CORRECT
|
||||
& ~InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS
|
||||
| InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS
|
||||
| InputType.TYPE_TEXT_FLAG_CAP_WORDS);
|
||||
mFolderName.forceDisableSuggestions(!FeatureFlags.FOLDER_NAME_SUGGEST.get());
|
||||
mFolderName.forceDisableSuggestions(true);
|
||||
|
||||
mFooter = findViewById(R.id.folder_footer);
|
||||
|
||||
|
@ -741,7 +741,8 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
|
|||
|
||||
@Override
|
||||
protected View getAccessibilityInitialFocusView() {
|
||||
return mContent.getFirstItem();
|
||||
View firstItem = mContent.getFirstItem();
|
||||
return firstItem != null ? firstItem : super.getAccessibilityInitialFocusView();
|
||||
}
|
||||
|
||||
private void closeComplete(boolean wasAnimated) {
|
||||
|
|
|
@ -126,7 +126,7 @@ public class LauncherPreviewRenderer {
|
|||
*/
|
||||
public static class PreviewContext extends ContextWrapper {
|
||||
|
||||
private static final Set<MainThreadInitializedObject> WHITELIST = new HashSet<>(
|
||||
private final Set<MainThreadInitializedObject> mAllowedObjects = new HashSet<>(
|
||||
Arrays.asList(UserCache.INSTANCE, InstallSessionHelper.INSTANCE,
|
||||
LauncherAppState.INSTANCE, InvariantDeviceProfile.INSTANCE,
|
||||
CustomWidgetManager.INSTANCE, PluginManagerWrapper.INSTANCE));
|
||||
|
@ -160,7 +160,7 @@ public class LauncherPreviewRenderer {
|
|||
*/
|
||||
public <T> T getObject(MainThreadInitializedObject<T> mainThreadInitializedObject,
|
||||
MainThreadInitializedObject.ObjectProvider<T> provider) {
|
||||
if (!WHITELIST.contains(mainThreadInitializedObject)) {
|
||||
if (!mAllowedObjects.contains(mainThreadInitializedObject)) {
|
||||
throw new IllegalStateException("Leaking unknown objects");
|
||||
}
|
||||
if (mainThreadInitializedObject == LauncherAppState.INSTANCE) {
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
*/
|
||||
package com.android.launcher3.logging;
|
||||
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.IGNORE;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_CLOSE_DOWN;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_OPEN_UP;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_HOME_GESTURE;
|
||||
|
@ -23,8 +22,6 @@ import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCH
|
|||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.logger.LauncherAtom.ContainerInfo;
|
||||
import com.android.launcher3.logger.LauncherAtom.FromState;
|
||||
|
@ -403,19 +400,6 @@ public class StatsLogManager implements ResourceBasedOverride {
|
|||
return mgr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Log an event with ranked-choice information along with package. Does nothing if event.getId()
|
||||
* <= 0.
|
||||
*
|
||||
* @param rankingEvent an enum implementing EventEnum interface.
|
||||
* @param instanceId An identifier obtained from an InstanceIdSequence.
|
||||
* @param packageName the package name of the relevant app, if known (null otherwise).
|
||||
* @param position the position picked.
|
||||
*/
|
||||
public void log(EventEnum rankingEvent, InstanceId instanceId, @Nullable String packageName,
|
||||
int position) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs snapshot, or impression of the current workspace.
|
||||
*/
|
||||
|
|
|
@ -17,13 +17,7 @@ package com.android.launcher3.model;
|
|||
|
||||
import static com.android.launcher3.util.MainThreadInitializedObject.forOverride;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.os.UserHandle;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
||||
import com.android.launcher3.util.MainThreadInitializedObject;
|
||||
import com.android.launcher3.util.ResourceBasedOverride;
|
||||
|
||||
|
@ -32,28 +26,8 @@ import com.android.launcher3.util.ResourceBasedOverride;
|
|||
*/
|
||||
public class AppLaunchTracker implements ResourceBasedOverride {
|
||||
|
||||
/**
|
||||
* Derived from LauncherEvent proto.
|
||||
* TODO: Use proper descriptive constants
|
||||
*/
|
||||
public static final String CONTAINER_DEFAULT = Integer.toString(ContainerType.WORKSPACE);
|
||||
public static final String CONTAINER_ALL_APPS = Integer.toString(ContainerType.ALLAPPS);
|
||||
public static final String CONTAINER_PREDICTIONS = Integer.toString(ContainerType.PREDICTION);
|
||||
public static final String CONTAINER_SEARCH = Integer.toString(ContainerType.SEARCHRESULT);
|
||||
public static final String CONTAINER_OVERVIEW = Integer.toString(ContainerType.OVERVIEW);
|
||||
|
||||
|
||||
public static final MainThreadInitializedObject<AppLaunchTracker> INSTANCE =
|
||||
forOverride(AppLaunchTracker.class, R.string.app_launch_tracker_class);
|
||||
|
||||
public void onStartShortcut(String packageName, String shortcutId, UserHandle user,
|
||||
@Nullable String container) { }
|
||||
|
||||
public void onStartApp(ComponentName componentName, UserHandle user,
|
||||
@Nullable String container) { }
|
||||
|
||||
public void onDismissApp(ComponentName componentName, UserHandle user,
|
||||
@Nullable String container){}
|
||||
|
||||
public void onReturnedToHome() { }
|
||||
}
|
||||
|
|
|
@ -56,6 +56,7 @@ import java.util.Iterator;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
|
@ -348,6 +349,19 @@ public class BgDataModel {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the provided {@code op} for all workspaceItems in the in-memory model (both persisted
|
||||
* items and dynamic/predicted items for the provided {@code userHandle}.
|
||||
* Note the call is not synchronized over the model, that should be handled by the called.
|
||||
*/
|
||||
public void forAllWorkspaceItemInfos(UserHandle userHandle, Consumer<WorkspaceItemInfo> op) {
|
||||
for (ItemInfo info : itemsIdMap) {
|
||||
if (info instanceof WorkspaceItemInfo && userHandle.equals(info.user)) {
|
||||
op.accept((WorkspaceItemInfo) info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface Callbacks {
|
||||
// If the launcher has permission to access deep shortcuts.
|
||||
int FLAG_HAS_SHORTCUT_PERMISSION = 1 << 0;
|
||||
|
|
|
@ -21,7 +21,6 @@ import android.os.UserHandle;
|
|||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.LauncherSettings;
|
||||
import com.android.launcher3.icons.IconCache;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -48,14 +47,10 @@ public class CacheDataUpdatedTask extends BaseModelUpdateTask {
|
|||
@Override
|
||||
public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) {
|
||||
IconCache iconCache = app.getIconCache();
|
||||
|
||||
|
||||
ArrayList<WorkspaceItemInfo> updatedShortcuts = new ArrayList<>();
|
||||
|
||||
synchronized (dataModel) {
|
||||
for (ItemInfo info : dataModel.itemsIdMap) {
|
||||
if (info instanceof WorkspaceItemInfo && mUser.equals(info.user)) {
|
||||
WorkspaceItemInfo si = (WorkspaceItemInfo) info;
|
||||
dataModel.forAllWorkspaceItemInfos(mUser, si -> {
|
||||
ComponentName cn = si.getTargetComponent();
|
||||
if (si.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION
|
||||
&& isValidShortcut(si) && cn != null
|
||||
|
@ -63,8 +58,7 @@ public class CacheDataUpdatedTask extends BaseModelUpdateTask {
|
|||
iconCache.getTitleAndIcon(si, si.usingLowResIcon());
|
||||
updatedShortcuts.add(si);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
apps.updateIconsAndLabels(mPackages, mUser);
|
||||
}
|
||||
bindUpdatedWorkspaceItems(updatedShortcuts);
|
||||
|
|
|
@ -20,8 +20,6 @@ import android.content.pm.ApplicationInfo;
|
|||
import android.content.pm.PackageManager;
|
||||
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.LauncherModel.CallbackTask;
|
||||
import com.android.launcher3.model.BgDataModel.Callbacks;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
|
||||
import com.android.launcher3.model.data.PromiseAppInfo;
|
||||
|
@ -70,9 +68,7 @@ public class PackageInstallStateChangedTask extends BaseModelUpdateTask {
|
|||
|
||||
synchronized (dataModel) {
|
||||
final HashSet<ItemInfo> updates = new HashSet<>();
|
||||
for (ItemInfo info : dataModel.itemsIdMap) {
|
||||
if (info instanceof WorkspaceItemInfo) {
|
||||
WorkspaceItemInfo si = (WorkspaceItemInfo) info;
|
||||
dataModel.forAllWorkspaceItemInfos(mInstallInfo.user, si -> {
|
||||
ComponentName cn = si.getTargetComponent();
|
||||
if (si.hasPromiseIconUi() && (cn != null)
|
||||
&& mInstallInfo.packageName.equals(cn.getPackageName())) {
|
||||
|
@ -83,8 +79,7 @@ public class PackageInstallStateChangedTask extends BaseModelUpdateTask {
|
|||
}
|
||||
updates.add(si);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
for (LauncherAppWidgetInfo widget : dataModel.appWidgets) {
|
||||
if (widget.providerName.getPackageName().equals(mInstallInfo.packageName)) {
|
||||
|
@ -94,12 +89,7 @@ public class PackageInstallStateChangedTask extends BaseModelUpdateTask {
|
|||
}
|
||||
|
||||
if (!updates.isEmpty()) {
|
||||
scheduleCallbackTask(new CallbackTask() {
|
||||
@Override
|
||||
public void execute(Callbacks callbacks) {
|
||||
callbacks.bindRestoreItemsChange(updates);
|
||||
}
|
||||
});
|
||||
scheduleCallbackTask(callbacks -> callbacks.bindRestoreItemsChange(updates));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ import com.android.launcher3.model.data.WorkspaceItemInfo;
|
|||
import com.android.launcher3.pm.UserCache;
|
||||
import com.android.launcher3.shortcuts.ShortcutRequest;
|
||||
import com.android.launcher3.util.FlagOp;
|
||||
import com.android.launcher3.util.IntSparseArrayMap;
|
||||
import com.android.launcher3.util.IntSet;
|
||||
import com.android.launcher3.util.ItemInfoMatcher;
|
||||
import com.android.launcher3.util.PackageManagerHelper;
|
||||
import com.android.launcher3.util.PackageUserKey;
|
||||
|
@ -92,9 +92,11 @@ public class PackageUpdatedTask extends BaseModelUpdateTask {
|
|||
|
||||
final String[] packages = mPackages;
|
||||
final int N = packages.length;
|
||||
FlagOp flagOp = FlagOp.NO_OP;
|
||||
final FlagOp flagOp;
|
||||
final HashSet<String> packageSet = new HashSet<>(Arrays.asList(packages));
|
||||
ItemInfoMatcher matcher = ItemInfoMatcher.ofPackages(packageSet, mUser);
|
||||
final ItemInfoMatcher matcher = mOp == OP_USER_AVAILABILITY_CHANGE
|
||||
? ItemInfoMatcher.ofUser(mUser) // We want to update all packages for this user
|
||||
: ItemInfoMatcher.ofPackages(packageSet, mUser);
|
||||
final HashSet<ComponentName> removedComponents = new HashSet<>();
|
||||
|
||||
switch (mOp) {
|
||||
|
@ -158,19 +160,22 @@ public class PackageUpdatedTask extends BaseModelUpdateTask {
|
|||
flagOp = ums.isUserQuiet(mUser)
|
||||
? FlagOp.addFlag(WorkspaceItemInfo.FLAG_DISABLED_QUIET_USER)
|
||||
: FlagOp.removeFlag(WorkspaceItemInfo.FLAG_DISABLED_QUIET_USER);
|
||||
// We want to update all packages for this user.
|
||||
matcher = ItemInfoMatcher.ofUser(mUser);
|
||||
appsList.updateDisabledFlags(matcher, flagOp);
|
||||
|
||||
// We are not synchronizing here, as int operations are atomic
|
||||
appsList.setFlags(FLAG_QUIET_MODE_ENABLED, ums.isAnyProfileQuietModeEnabled());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
flagOp = FlagOp.NO_OP;
|
||||
break;
|
||||
}
|
||||
|
||||
bindApplicationsIfNeeded();
|
||||
|
||||
final IntSparseArrayMap<Boolean> removedShortcuts = new IntSparseArrayMap<>();
|
||||
final IntSet removedShortcuts = new IntSet();
|
||||
// Shortcuts to keep even if the corresponding app was removed
|
||||
final IntSet forceKeepShortcuts = new IntSet();
|
||||
|
||||
// Update shortcut infos
|
||||
if (mOp == OP_ADD || flagOp != FlagOp.NO_OP) {
|
||||
|
@ -180,9 +185,8 @@ public class PackageUpdatedTask extends BaseModelUpdateTask {
|
|||
// For system apps, package manager send OP_UPDATE when an app is enabled.
|
||||
final boolean isNewApkAvailable = mOp == OP_ADD || mOp == OP_UPDATE;
|
||||
synchronized (dataModel) {
|
||||
for (ItemInfo info : dataModel.itemsIdMap) {
|
||||
if (info instanceof WorkspaceItemInfo && mUser.equals(info.user)) {
|
||||
WorkspaceItemInfo si = (WorkspaceItemInfo) info;
|
||||
dataModel.forAllWorkspaceItemInfos(mUser, si -> {
|
||||
|
||||
boolean infoUpdated = false;
|
||||
boolean shortcutUpdated = false;
|
||||
|
||||
|
@ -203,9 +207,9 @@ public class PackageUpdatedTask extends BaseModelUpdateTask {
|
|||
String packageName = cn.getPackageName();
|
||||
|
||||
if (si.hasStatusFlag(WorkspaceItemInfo.FLAG_SUPPORTS_WEB_UI)) {
|
||||
removedShortcuts.put(si.id, false);
|
||||
forceKeepShortcuts.add(si.id);
|
||||
if (mOp == OP_REMOVE) {
|
||||
continue;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -231,14 +235,14 @@ public class PackageUpdatedTask extends BaseModelUpdateTask {
|
|||
if (updateWorkspaceItemIntent(context, si, packageName)) {
|
||||
infoUpdated = true;
|
||||
} else if (si.hasPromiseIconUi()) {
|
||||
removedShortcuts.put(si.id, true);
|
||||
continue;
|
||||
removedShortcuts.add(si.id);
|
||||
return;
|
||||
}
|
||||
} else if (!isTargetValid) {
|
||||
removedShortcuts.put(si.id, true);
|
||||
removedShortcuts.add(si.id);
|
||||
FileLog.e(TAG, "Restored shortcut no longer valid "
|
||||
+ si.getIntent());
|
||||
continue;
|
||||
return;
|
||||
} else {
|
||||
si.status = WorkspaceItemInfo.DEFAULT;
|
||||
infoUpdated = true;
|
||||
|
@ -249,8 +253,8 @@ public class PackageUpdatedTask extends BaseModelUpdateTask {
|
|||
}
|
||||
}
|
||||
|
||||
if (isNewApkAvailable &&
|
||||
si.itemType == Favorites.ITEM_TYPE_APPLICATION) {
|
||||
if (isNewApkAvailable
|
||||
&& si.itemType == Favorites.ITEM_TYPE_APPLICATION) {
|
||||
iconCache.getTitleAndIcon(si, si.usingLowResIcon());
|
||||
infoUpdated = true;
|
||||
}
|
||||
|
@ -265,17 +269,19 @@ public class PackageUpdatedTask extends BaseModelUpdateTask {
|
|||
if (infoUpdated || shortcutUpdated) {
|
||||
updatedWorkspaceItems.add(si);
|
||||
}
|
||||
if (infoUpdated) {
|
||||
if (infoUpdated && si.id != ItemInfo.NO_ID) {
|
||||
getModelWriter().updateItemInDatabase(si);
|
||||
}
|
||||
} else if (info instanceof LauncherAppWidgetInfo && isNewApkAvailable) {
|
||||
LauncherAppWidgetInfo widgetInfo = (LauncherAppWidgetInfo) info;
|
||||
});
|
||||
|
||||
for (LauncherAppWidgetInfo widgetInfo : dataModel.appWidgets) {
|
||||
if (mUser.equals(widgetInfo.user)
|
||||
&& widgetInfo.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY)
|
||||
&& widgetInfo.hasRestoreFlag(
|
||||
LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY)
|
||||
&& packageSet.contains(widgetInfo.providerName.getPackageName())) {
|
||||
widgetInfo.restoreStatus &=
|
||||
~LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY &
|
||||
~LauncherAppWidgetInfo.FLAG_RESTORE_STARTED;
|
||||
~LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY
|
||||
& ~LauncherAppWidgetInfo.FLAG_RESTORE_STARTED;
|
||||
|
||||
// adding this flag ensures that launcher shows 'click to setup'
|
||||
// if the widget has a config activity. In case there is no config
|
||||
|
@ -287,11 +293,10 @@ public class PackageUpdatedTask extends BaseModelUpdateTask {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bindUpdatedWorkspaceItems(updatedWorkspaceItems);
|
||||
if (!removedShortcuts.isEmpty()) {
|
||||
deleteAndBindComponentsRemoved(ItemInfoMatcher.ofItemIds(removedShortcuts, false));
|
||||
deleteAndBindComponentsRemoved(ItemInfoMatcher.ofItemIds(removedShortcuts));
|
||||
}
|
||||
|
||||
if (!widgets.isEmpty()) {
|
||||
|
@ -319,7 +324,7 @@ public class PackageUpdatedTask extends BaseModelUpdateTask {
|
|||
if (!removedPackages.isEmpty() || !removedComponents.isEmpty()) {
|
||||
ItemInfoMatcher removeMatch = ItemInfoMatcher.ofPackages(removedPackages, mUser)
|
||||
.or(ItemInfoMatcher.ofComponents(removedComponents, mUser))
|
||||
.and(ItemInfoMatcher.ofItemIds(removedShortcuts, true));
|
||||
.and(ItemInfoMatcher.ofItemIds(forceKeepShortcuts).negate());
|
||||
deleteAndBindComponentsRemoved(removeMatch);
|
||||
|
||||
// Remove any queued items from the install queue
|
||||
|
|
|
@ -21,7 +21,6 @@ import android.os.UserHandle;
|
|||
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.LauncherSettings;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.shortcuts.ShortcutKey;
|
||||
import com.android.launcher3.shortcuts.ShortcutRequest;
|
||||
|
@ -58,14 +57,14 @@ public class ShortcutsChangedTask extends BaseModelUpdateTask {
|
|||
MultiHashMap<ShortcutKey, WorkspaceItemInfo> keyToShortcutInfo = new MultiHashMap<>();
|
||||
HashSet<String> allIds = new HashSet<>();
|
||||
|
||||
for (ItemInfo itemInfo : dataModel.itemsIdMap) {
|
||||
if (itemInfo.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
|
||||
WorkspaceItemInfo si = (WorkspaceItemInfo) itemInfo;
|
||||
if (mPackageName.equals(si.getIntent().getPackage()) && si.user.equals(mUser)) {
|
||||
synchronized (dataModel) {
|
||||
dataModel.forAllWorkspaceItemInfos(mUser, si -> {
|
||||
if ((si.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT)
|
||||
&& mPackageName.equals(si.getIntent().getPackage())) {
|
||||
keyToShortcutInfo.addToList(ShortcutKey.fromItemInfo(si), si);
|
||||
allIds.add(si.getDeepShortcutId());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
final ArrayList<WorkspaceItemInfo> updatedWorkspaceItemInfos = new ArrayList<>();
|
||||
|
|
|
@ -23,7 +23,6 @@ import android.os.UserHandle;
|
|||
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.LauncherSettings;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.shortcuts.ShortcutKey;
|
||||
import com.android.launcher3.shortcuts.ShortcutRequest;
|
||||
|
@ -73,10 +72,9 @@ public class UserLockStateChangedTask extends BaseModelUpdateTask {
|
|||
ArrayList<WorkspaceItemInfo> updatedWorkspaceItemInfos = new ArrayList<>();
|
||||
HashSet<ShortcutKey> removedKeys = new HashSet<>();
|
||||
|
||||
for (ItemInfo itemInfo : dataModel.itemsIdMap) {
|
||||
if (itemInfo.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT
|
||||
&& mUser.equals(itemInfo.user)) {
|
||||
WorkspaceItemInfo si = (WorkspaceItemInfo) itemInfo;
|
||||
synchronized (dataModel) {
|
||||
dataModel.forAllWorkspaceItemInfos(mUser, si -> {
|
||||
if (si.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
|
||||
if (mIsUserUnlocked) {
|
||||
ShortcutKey key = ShortcutKey.fromItemInfo(si);
|
||||
ShortcutInfo shortcut = pinnedShortcuts.get(key);
|
||||
|
@ -84,7 +82,7 @@ public class UserLockStateChangedTask extends BaseModelUpdateTask {
|
|||
// (probably due to clear data), delete the workspace item as well
|
||||
if (shortcut == null) {
|
||||
removedKeys.add(key);
|
||||
continue;
|
||||
return;
|
||||
}
|
||||
si.runtimeStatusFlags &= ~FLAG_DISABLED_LOCKED_USER;
|
||||
si.updateFromDeepShortcutInfo(shortcut, context);
|
||||
|
@ -94,6 +92,7 @@ public class UserLockStateChangedTask extends BaseModelUpdateTask {
|
|||
}
|
||||
updatedWorkspaceItemInfos.add(si);
|
||||
}
|
||||
});
|
||||
}
|
||||
bindUpdatedWorkspaceItems(updatedWorkspaceItemInfos);
|
||||
if (!removedKeys.isEmpty()) {
|
||||
|
|
|
@ -53,6 +53,7 @@ import com.android.launcher3.logger.LauncherAtom.SettingsContainer;
|
|||
import com.android.launcher3.logger.LauncherAtom.ShortcutsContainer;
|
||||
import com.android.launcher3.logger.LauncherAtom.TaskSwitcherContainer;
|
||||
import com.android.launcher3.model.ModelWriter;
|
||||
import com.android.launcher3.shortcuts.ShortcutKey;
|
||||
import com.android.launcher3.util.ContentWriter;
|
||||
|
||||
import java.util.Optional;
|
||||
|
@ -285,6 +286,13 @@ public class ItemInfo {
|
|||
.orElse(LauncherAtom.Application.newBuilder()));
|
||||
break;
|
||||
case ITEM_TYPE_DEEP_SHORTCUT:
|
||||
itemBuilder
|
||||
.setShortcut(nullableComponent
|
||||
.map(component -> LauncherAtom.Shortcut.newBuilder()
|
||||
.setShortcutName(component.flattenToShortString())
|
||||
.setShortcutId(ShortcutKey.fromItemInfo(this).getId()))
|
||||
.orElse(LauncherAtom.Shortcut.newBuilder()));
|
||||
break;
|
||||
case ITEM_TYPE_SHORTCUT:
|
||||
itemBuilder
|
||||
.setShortcut(nullableComponent
|
||||
|
|
|
@ -174,7 +174,7 @@ public abstract class SystemShortcut<T extends BaseDraggingActivity> extends Ite
|
|||
public void onClick(View view) {
|
||||
Intent intent = new PackageManagerHelper(view.getContext()).getMarketIntent(
|
||||
mItemInfo.getTargetComponent().getPackageName());
|
||||
mTarget.startActivitySafely(view, intent, mItemInfo, null);
|
||||
mTarget.startActivitySafely(view, intent, mItemInfo);
|
||||
AbstractFloatingView.closeAllOpenViews(mTarget);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,8 +15,6 @@
|
|||
*/
|
||||
package com.android.launcher3.secondarydisplay;
|
||||
|
||||
import static com.android.launcher3.model.AppLaunchTracker.CONTAINER_ALL_APPS;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.app.ActivityOptions;
|
||||
|
@ -327,7 +325,7 @@ public class SecondaryDisplayLauncher extends BaseDraggingActivity
|
|||
if (intent == null) {
|
||||
throw new IllegalArgumentException("Input must have a valid intent");
|
||||
}
|
||||
startActivitySafely(v, intent, item, CONTAINER_ALL_APPS);
|
||||
startActivitySafely(v, intent, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,6 @@ import android.graphics.Rect;
|
|||
import android.graphics.drawable.Drawable;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.android.launcher3.BubbleTextView;
|
||||
|
@ -106,12 +105,12 @@ public class DeepShortcutTextView extends BubbleTextView {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent ev) {
|
||||
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
|
||||
protected boolean shouldIgnoreTouchDown(float x, float y) {
|
||||
// Show toast if user touches the drag handle (long clicks still start the drag).
|
||||
mShowInstructionToast = mDragHandleBounds.contains((int) ev.getX(), (int) ev.getY());
|
||||
}
|
||||
return super.onTouchEvent(ev);
|
||||
mShowInstructionToast = mDragHandleBounds.contains((int) x, (int) y);
|
||||
|
||||
// assume the whole view as clickable
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -33,6 +33,7 @@ import com.android.launcher3.LauncherAppState;
|
|||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.util.ResourceBasedOverride;
|
||||
import com.android.launcher3.widget.WidgetsFullSheet;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.function.Function;
|
||||
|
@ -92,6 +93,11 @@ public class TestInformationHandler implements ResourceBasedOverride {
|
|||
l -> l.getAppsView().getActiveRecyclerView().getCurrentScrollY());
|
||||
}
|
||||
|
||||
case TestProtocol.REQUEST_WIDGETS_SCROLL_Y: {
|
||||
return getLauncherUIProperty(Bundle::putInt,
|
||||
l -> WidgetsFullSheet.getWidgetsView(l).getCurrentScrollY());
|
||||
}
|
||||
|
||||
case TestProtocol.REQUEST_WINDOW_INSETS: {
|
||||
return getUIProperty(Bundle::putParcelable, a -> {
|
||||
WindowInsets insets = a.getWindow()
|
||||
|
|
|
@ -81,6 +81,7 @@ public final class TestProtocol {
|
|||
public static final String REQUEST_UNFREEZE_APP_LIST = "unfreeze-app-list";
|
||||
public static final String REQUEST_APP_LIST_FREEZE_FLAGS = "app-list-freeze-flags";
|
||||
public static final String REQUEST_APPS_LIST_SCROLL_Y = "apps-list-scroll-y";
|
||||
public static final String REQUEST_WIDGETS_SCROLL_Y = "widgets-scroll-y";
|
||||
public static final String REQUEST_WINDOW_INSETS = "window-insets";
|
||||
public static final String REQUEST_PID = "pid";
|
||||
public static final String REQUEST_TOTAL_PSS_KB = "total_pss";
|
||||
|
@ -106,4 +107,5 @@ public final class TestProtocol {
|
|||
public static final String PAUSE_NOT_DETECTED = "b/139891609";
|
||||
public static final String OVERIEW_NOT_ALLAPPS = "b/156095088";
|
||||
public static final String NO_SWIPE_TO_HOME = "b/158017601";
|
||||
public static final String NO_SCROLL_END_WIDGETS = "b/160238801";
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@ package com.android.launcher3.touch;
|
|||
import static com.android.launcher3.Launcher.REQUEST_BIND_PENDING_APPWIDGET;
|
||||
import static com.android.launcher3.Launcher.REQUEST_RECONFIGURE_APPWIDGET;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_FOLDER_OPEN;
|
||||
import static com.android.launcher3.model.AppLaunchTracker.CONTAINER_ALL_APPS;
|
||||
import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_DISABLED_BY_PUBLISHER;
|
||||
import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_DISABLED_LOCKED_USER;
|
||||
import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_DISABLED_QUIET_USER;
|
||||
|
@ -37,8 +36,6 @@ import android.view.View;
|
|||
import android.view.View.OnClickListener;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.BubbleTextView;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherAppWidgetProviderInfo;
|
||||
|
@ -72,13 +69,9 @@ public class ItemClickHandler {
|
|||
/**
|
||||
* Instance used for click handling on items
|
||||
*/
|
||||
public static final OnClickListener INSTANCE = getInstance(null);
|
||||
public static final OnClickListener INSTANCE = ItemClickHandler::onClick;
|
||||
|
||||
public static final OnClickListener getInstance(String sourceContainer) {
|
||||
return v -> onClick(v, sourceContainer);
|
||||
}
|
||||
|
||||
private static void onClick(View v, String sourceContainer) {
|
||||
private static void onClick(View v) {
|
||||
// Make sure that rogue clicks don't get through while allapps is launching, or after the
|
||||
// view has detached (it's possible for this to happen if the view is removed mid touch).
|
||||
if (v.getWindowToken() == null) return;
|
||||
|
@ -88,14 +81,14 @@ public class ItemClickHandler {
|
|||
|
||||
Object tag = v.getTag();
|
||||
if (tag instanceof WorkspaceItemInfo) {
|
||||
onClickAppShortcut(v, (WorkspaceItemInfo) tag, launcher, sourceContainer);
|
||||
onClickAppShortcut(v, (WorkspaceItemInfo) tag, launcher);
|
||||
} else if (tag instanceof FolderInfo) {
|
||||
if (v instanceof FolderIcon) {
|
||||
onClickFolderIcon(v);
|
||||
}
|
||||
} else if (tag instanceof AppInfo) {
|
||||
startAppShortcutOrInfoActivity(v, (AppInfo) tag, launcher,
|
||||
sourceContainer == null ? CONTAINER_ALL_APPS: sourceContainer);
|
||||
startAppShortcutOrInfoActivity(v, (AppInfo) tag, launcher
|
||||
);
|
||||
} else if (tag instanceof LauncherAppWidgetInfo) {
|
||||
if (v instanceof PendingAppWidgetHostView) {
|
||||
onClickPendingWidget((PendingAppWidgetHostView) v, launcher);
|
||||
|
@ -191,7 +184,7 @@ public class ItemClickHandler {
|
|||
|
||||
// Fallback to using custom market intent.
|
||||
Intent intent = new PackageManagerHelper(launcher).getMarketIntent(packageName);
|
||||
launcher.startActivitySafely(v, intent, item, null);
|
||||
launcher.startActivitySafely(v, intent, item);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -199,8 +192,7 @@ public class ItemClickHandler {
|
|||
*
|
||||
* @param v The view that was clicked. Must be a tagged with a {@link WorkspaceItemInfo}.
|
||||
*/
|
||||
public static void onClickAppShortcut(View v, WorkspaceItemInfo shortcut, Launcher launcher,
|
||||
@Nullable String sourceContainer) {
|
||||
public static void onClickAppShortcut(View v, WorkspaceItemInfo shortcut, Launcher launcher) {
|
||||
if (shortcut.isDisabled()) {
|
||||
final int disabledFlags = shortcut.runtimeStatusFlags
|
||||
& WorkspaceItemInfo.FLAG_DISABLED_MASK;
|
||||
|
@ -241,11 +233,10 @@ public class ItemClickHandler {
|
|||
}
|
||||
|
||||
// Start activities
|
||||
startAppShortcutOrInfoActivity(v, shortcut, launcher, sourceContainer);
|
||||
startAppShortcutOrInfoActivity(v, shortcut, launcher);
|
||||
}
|
||||
|
||||
private static void startAppShortcutOrInfoActivity(View v, ItemInfo item, Launcher launcher,
|
||||
@Nullable String sourceContainer) {
|
||||
private static void startAppShortcutOrInfoActivity(View v, ItemInfo item, Launcher launcher) {
|
||||
TestLogging.recordEvent(
|
||||
TestProtocol.SEQUENCE_MAIN, "start: startAppShortcutOrInfoActivity");
|
||||
Intent intent;
|
||||
|
@ -274,6 +265,6 @@ public class ItemClickHandler {
|
|||
// Preload the icon to reduce latency b/w swapping the floating view with the original.
|
||||
FloatingIconView.fetchIcon(launcher, v, item, true /* isOpening */);
|
||||
}
|
||||
launcher.startActivitySafely(v, intent, item, sourceContainer);
|
||||
launcher.startActivitySafely(v, intent, item);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package com.android.launcher3.touch;
|
||||
|
||||
import static android.widget.ListPopupWindow.WRAP_CONTENT;
|
||||
|
||||
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
|
||||
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
|
||||
import static com.android.launcher3.touch.SingleAxisSwipeDetector.HORIZONTAL;
|
||||
|
@ -33,6 +34,7 @@ import android.view.View;
|
|||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.PagedView;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.util.OverScroller;
|
||||
|
@ -237,7 +239,8 @@ public class LandscapePagedViewHandler implements PagedOrientationHandler {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int getTaskMenuLayoutOrientation(LinearLayout taskMenuLayout) {
|
||||
public int getTaskMenuLayoutOrientation(boolean canRecentsActivityRotate,
|
||||
LinearLayout taskMenuLayout) {
|
||||
return LinearLayout.HORIZONTAL;
|
||||
}
|
||||
|
||||
|
@ -260,4 +263,10 @@ public class LandscapePagedViewHandler implements PagedOrientationHandler {
|
|||
}
|
||||
return new ChildBounds(childHeight, childWidth, childBottom, childLeft);
|
||||
}
|
||||
|
||||
@SuppressWarnings("SuspiciousNameCombination")
|
||||
@Override
|
||||
public int getDistanceToBottomOfRect(DeviceProfile dp, Rect rect) {
|
||||
return rect.left;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -94,8 +94,9 @@ public interface PagedOrientationHandler {
|
|||
float getTaskMenuX(float x, View thumbnailView);
|
||||
float getTaskMenuY(float y, View thumbnailView);
|
||||
int getTaskMenuWidth(View view);
|
||||
int getTaskMenuLayoutOrientation(LinearLayout taskMenuLayout);
|
||||
int getTaskMenuLayoutOrientation(boolean canRecentsActivityRotate, LinearLayout taskMenuLayout);
|
||||
void setLayoutParamsForTaskMenuOptionItem(LinearLayout.LayoutParams lp);
|
||||
int getDistanceToBottomOfRect(DeviceProfile dp, Rect rect);
|
||||
|
||||
/**
|
||||
* Maps the velocity from the coordinate plane of the foreground app to that
|
||||
|
|
|
@ -32,6 +32,7 @@ import android.view.View;
|
|||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.PagedView;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.util.OverScroller;
|
||||
|
@ -236,8 +237,9 @@ public class PortraitPagedViewHandler implements PagedOrientationHandler {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int getTaskMenuLayoutOrientation(LinearLayout taskMenuLayout) {
|
||||
return taskMenuLayout.getOrientation();
|
||||
public int getTaskMenuLayoutOrientation(boolean canRecentsActivityRotate,
|
||||
LinearLayout taskMenuLayout) {
|
||||
return canRecentsActivityRotate ? taskMenuLayout.getOrientation() : LinearLayout.VERTICAL;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -257,4 +259,9 @@ public class PortraitPagedViewHandler implements PagedOrientationHandler {
|
|||
}
|
||||
return new ChildBounds(childWidth, childHeight, childRight, childTop);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDistanceToBottomOfRect(DeviceProfile dp, Rect rect) {
|
||||
return dp.heightPx - rect.bottom;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,9 +18,11 @@ package com.android.launcher3.touch;
|
|||
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.Rect;
|
||||
import android.view.Surface;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.Utilities;
|
||||
|
||||
public class SeascapePagedViewHandler extends LandscapePagedViewHandler {
|
||||
|
@ -77,4 +79,9 @@ public class SeascapePagedViewHandler extends LandscapePagedViewHandler {
|
|||
view.setTranslationX(0);
|
||||
view.setTranslationY(translation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDistanceToBottomOfRect(DeviceProfile dp, Rect rect) {
|
||||
return dp.widthPx - rect.right;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -81,11 +81,10 @@ public interface ItemInfoMatcher {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns a new matcher which returns the opposite boolean value of the provided
|
||||
* {@param matcher}.
|
||||
* Returns a new matcher with returns the opposite value of this.
|
||||
*/
|
||||
static ItemInfoMatcher not(ItemInfoMatcher matcher) {
|
||||
return (info, cn) -> !matcher.matches(info, cn);
|
||||
default ItemInfoMatcher negate() {
|
||||
return (info, cn) -> !matches(info, cn);
|
||||
}
|
||||
|
||||
static ItemInfoMatcher ofUser(UserHandle user) {
|
||||
|
@ -105,7 +104,10 @@ public interface ItemInfoMatcher {
|
|||
keys.contains(ShortcutKey.fromItemInfo(info));
|
||||
}
|
||||
|
||||
static ItemInfoMatcher ofItemIds(IntSparseArrayMap<Boolean> ids, Boolean matchDefault) {
|
||||
return (info, cn) -> ids.get(info.id, matchDefault);
|
||||
/**
|
||||
* Returns a matcher for items with provided ids
|
||||
*/
|
||||
static ItemInfoMatcher ofItemIds(IntSet ids) {
|
||||
return (info, cn) -> ids.contains(info.id);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ public class MainThreadInitializedObject<T> {
|
|||
|
||||
if (mValue == null) {
|
||||
if (Looper.myLooper() == Looper.getMainLooper()) {
|
||||
mValue = TraceHelper.whitelistIpcs("main.thread.object",
|
||||
mValue = TraceHelper.allowIpcs("main.thread.object",
|
||||
() -> mProvider.get(context.getApplicationContext()));
|
||||
} else {
|
||||
try {
|
||||
|
|
|
@ -64,7 +64,7 @@ public class OnboardingPrefs<T extends Launcher> {
|
|||
|
||||
private static final Map<String, Integer> MAX_COUNTS;
|
||||
static {
|
||||
Map<String, Integer> maxCounts = new ArrayMap<>(3);
|
||||
Map<String, Integer> maxCounts = new ArrayMap<>(4);
|
||||
maxCounts.put(HOME_BOUNCE_COUNT, 3);
|
||||
maxCounts.put(SHELF_BOUNCE_COUNT, 3);
|
||||
maxCounts.put(ALL_APPS_COUNT, 5);
|
||||
|
|
|
@ -78,7 +78,7 @@ public class TraceHelper {
|
|||
* Temporarily ignore blocking binder calls for the duration of this {@link Supplier}.
|
||||
*/
|
||||
@MainThread
|
||||
public static <T> T whitelistIpcs(String rpcName, Supplier<T> supplier) {
|
||||
public static <T> T allowIpcs(String rpcName, Supplier<T> supplier) {
|
||||
Object traceToken = INSTANCE.beginSection(rpcName, FLAG_IGNORE_BINDERS);
|
||||
try {
|
||||
return supplier.get();
|
||||
|
|
|
@ -292,6 +292,9 @@ public abstract class BaseDragLayer<T extends Context & ActivityContext>
|
|||
|
||||
@Override
|
||||
public boolean dispatchTouchEvent(MotionEvent ev) {
|
||||
if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
|
||||
Log.d(TestProtocol.NO_SCROLL_END_WIDGETS, "BaseDragLayer: " + ev);
|
||||
}
|
||||
switch (ev.getAction()) {
|
||||
case ACTION_DOWN: {
|
||||
if ((mTouchDispatchState & TOUCH_DISPATCHING_TO_VIEW_IN_PROGRESS) != 0) {
|
||||
|
@ -602,13 +605,13 @@ public abstract class BaseDragLayer<T extends Context & ActivityContext>
|
|||
*/
|
||||
private boolean computeAllowSysuiScrims(@Nullable WallpaperInfo newWallpaperInfo) {
|
||||
if (newWallpaperInfo == null) {
|
||||
// New wallpaper is static, not live. Thus, blacklist isn't applicable.
|
||||
// Static wallpapers need scrim unless determined otherwise by wallpaperColors.
|
||||
return true;
|
||||
}
|
||||
ComponentName newWallpaper = newWallpaperInfo.getComponent();
|
||||
for (String wallpaperWithoutScrim : mWallpapersWithoutSysuiScrims) {
|
||||
if (newWallpaper.equals(ComponentName.unflattenFromString(wallpaperWithoutScrim))) {
|
||||
// New wallpaper is blacklisted from showing a scrim.
|
||||
// New wallpaper does not need a scrim.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ import android.graphics.drawable.Drawable;
|
|||
import android.os.Build;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup.MarginLayoutParams;
|
||||
import android.view.ViewOutlineProvider;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
@ -44,8 +45,6 @@ import androidx.dynamicanimation.animation.SpringAnimation;
|
|||
import androidx.dynamicanimation.animation.SpringForce;
|
||||
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.InsettableFrameLayout.LayoutParams;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.dragndrop.FolderAdaptiveIcon;
|
||||
|
@ -94,7 +93,6 @@ public class ClipIconView extends View implements ClipPathView {
|
|||
}
|
||||
};
|
||||
|
||||
private final Launcher mLauncher;
|
||||
private final int mBlurSizeOutline;
|
||||
private final boolean mIsRtl;
|
||||
|
||||
|
@ -128,7 +126,6 @@ public class ClipIconView extends View implements ClipPathView {
|
|||
|
||||
public ClipIconView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
mLauncher = Launcher.getLauncher(context);
|
||||
mBlurSizeOutline = getResources().getDimensionPixelSize(
|
||||
R.dimen.blur_size_medium_outline);
|
||||
mIsRtl = Utilities.isRtl(getResources());
|
||||
|
@ -143,10 +140,41 @@ public class ClipIconView extends View implements ClipPathView {
|
|||
.setStiffness(SpringForce.STIFFNESS_LOW));
|
||||
}
|
||||
|
||||
void update(RectF rect, float progress, float shapeProgressStart, float cornerRadius,
|
||||
boolean isOpening, float scale, float minSize, LayoutParams parentLp,
|
||||
boolean isVerticalBarLayout) {
|
||||
DeviceProfile dp = mLauncher.getDeviceProfile();
|
||||
/**
|
||||
* Update the icon UI to match the provided parameters during an animation frame
|
||||
*/
|
||||
public void update(RectF rect, float progress, float shapeProgressStart,
|
||||
float cornerRadius, boolean isOpening, View container,
|
||||
DeviceProfile dp, boolean isVerticalBarLayout) {
|
||||
|
||||
MarginLayoutParams lp = (MarginLayoutParams) container.getLayoutParams();
|
||||
|
||||
float dX = mIsRtl
|
||||
? rect.left - (dp.widthPx - lp.getMarginStart() - lp.width)
|
||||
: rect.left - lp.getMarginStart();
|
||||
float dY = rect.top - lp.topMargin;
|
||||
container.setTranslationX(dX);
|
||||
container.setTranslationY(dY);
|
||||
|
||||
float minSize = Math.min(lp.width, lp.height);
|
||||
float scaleX = rect.width() / minSize;
|
||||
float scaleY = rect.height() / minSize;
|
||||
float scale = Math.max(1f, Math.min(scaleX, scaleY));
|
||||
|
||||
update(rect, progress, shapeProgressStart, cornerRadius, isOpening, scale,
|
||||
minSize, lp, isVerticalBarLayout, dp);
|
||||
|
||||
container.setPivotX(0);
|
||||
container.setPivotY(0);
|
||||
container.setScaleX(scale);
|
||||
container.setScaleY(scale);
|
||||
|
||||
container.invalidate();
|
||||
}
|
||||
|
||||
private void update(RectF rect, float progress, float shapeProgressStart, float cornerRadius,
|
||||
boolean isOpening, float scale, float minSize, MarginLayoutParams parentLp,
|
||||
boolean isVerticalBarLayout, DeviceProfile dp) {
|
||||
float dX = mIsRtl
|
||||
? rect.left - (dp.widthPx - parentLp.getMarginStart() - parentLp.width)
|
||||
: rect.left - parentLp.getMarginStart();
|
||||
|
@ -228,8 +256,11 @@ public class ClipIconView extends View implements ClipPathView {
|
|||
}
|
||||
}
|
||||
|
||||
void setIcon(@Nullable Drawable drawable, int iconOffset, LayoutParams lp, boolean isOpening,
|
||||
boolean isVerticalBarLayout) {
|
||||
/**
|
||||
* Sets the icon for this view as part of initial setup
|
||||
*/
|
||||
public void setIcon(@Nullable Drawable drawable, int iconOffset, MarginLayoutParams lp,
|
||||
boolean isOpening, boolean isVerticalBarLayout, DeviceProfile dp) {
|
||||
mIsAdaptiveIcon = drawable instanceof AdaptiveIconDrawable;
|
||||
if (mIsAdaptiveIcon) {
|
||||
boolean isFolderIcon = drawable instanceof FolderAdaptiveIcon;
|
||||
|
@ -264,15 +295,14 @@ public class ClipIconView extends View implements ClipPathView {
|
|||
Utilities.scaleRectAboutCenter(mStartRevealRect, IconShape.getNormalizationScale());
|
||||
}
|
||||
|
||||
float aspectRatio = mLauncher.getDeviceProfile().aspectRatio;
|
||||
if (isVerticalBarLayout) {
|
||||
lp.width = (int) Math.max(lp.width, lp.height * aspectRatio);
|
||||
lp.width = (int) Math.max(lp.width, lp.height * dp.aspectRatio);
|
||||
} else {
|
||||
lp.height = (int) Math.max(lp.height, lp.width * aspectRatio);
|
||||
lp.height = (int) Math.max(lp.height, lp.width * dp.aspectRatio);
|
||||
}
|
||||
|
||||
int left = mIsRtl
|
||||
? mLauncher.getDeviceProfile().widthPx - lp.getMarginStart() - lp.width
|
||||
? dp.widthPx - lp.getMarginStart() - lp.width
|
||||
: lp.leftMargin;
|
||||
layout(left, lp.topMargin, left + lp.width, lp.topMargin + lp.height);
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ import static com.android.launcher3.Utilities.getBadge;
|
|||
import static com.android.launcher3.Utilities.getFullDrawable;
|
||||
import static com.android.launcher3.config.FeatureFlags.ADAPTIVE_ICON_WINDOW_ANIM;
|
||||
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
|
||||
import static com.android.launcher3.views.IconLabelDotView.setIconAndDotVisible;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
|
@ -47,7 +48,6 @@ import androidx.annotation.UiThread;
|
|||
import androidx.annotation.WorkerThread;
|
||||
|
||||
import com.android.launcher3.BubbleTextView;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.InsettableFrameLayout;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.R;
|
||||
|
@ -144,32 +144,8 @@ public class FloatingIconView extends FrameLayout implements
|
|||
public void update(RectF rect, float alpha, float progress, float shapeProgressStart,
|
||||
float cornerRadius, boolean isOpening) {
|
||||
setAlpha(alpha);
|
||||
|
||||
InsettableFrameLayout.LayoutParams lp =
|
||||
(InsettableFrameLayout.LayoutParams) getLayoutParams();
|
||||
|
||||
DeviceProfile dp = mLauncher.getDeviceProfile();
|
||||
float dX = mIsRtl
|
||||
? rect.left - (dp.widthPx - lp.getMarginStart() - lp.width)
|
||||
: rect.left - lp.getMarginStart();
|
||||
float dY = rect.top - lp.topMargin;
|
||||
setTranslationX(dX);
|
||||
setTranslationY(dY);
|
||||
|
||||
float minSize = Math.min(lp.width, lp.height);
|
||||
float scaleX = rect.width() / minSize;
|
||||
float scaleY = rect.height() / minSize;
|
||||
float scale = Math.max(1f, Math.min(scaleX, scaleY));
|
||||
|
||||
mClipIconView.update(rect, progress, shapeProgressStart, cornerRadius, isOpening, scale,
|
||||
minSize, lp, mIsVerticalBarLayout);
|
||||
|
||||
setPivotX(0);
|
||||
setPivotY(0);
|
||||
setScaleX(scale);
|
||||
setScaleY(scale);
|
||||
|
||||
invalidate();
|
||||
mClipIconView.update(rect, progress, shapeProgressStart, cornerRadius, isOpening,
|
||||
this, mLauncher.getDeviceProfile(), mIsVerticalBarLayout);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -336,7 +312,8 @@ public class FloatingIconView extends FrameLayout implements
|
|||
final InsettableFrameLayout.LayoutParams lp =
|
||||
(InsettableFrameLayout.LayoutParams) getLayoutParams();
|
||||
mBadge = badge;
|
||||
mClipIconView.setIcon(drawable, iconOffset, lp, mIsOpening, mIsVerticalBarLayout);
|
||||
mClipIconView.setIcon(drawable, iconOffset, lp, mIsOpening, mIsVerticalBarLayout,
|
||||
mLauncher.getDeviceProfile());
|
||||
if (drawable instanceof AdaptiveIconDrawable) {
|
||||
final int originalHeight = lp.height;
|
||||
final int originalWidth = lp.width;
|
||||
|
@ -381,7 +358,7 @@ public class FloatingIconView extends FrameLayout implements
|
|||
if (mIconLoadResult.isIconLoaded) {
|
||||
setIcon(mIconLoadResult.drawable, mIconLoadResult.badge,
|
||||
mIconLoadResult.iconOffset);
|
||||
hideOriginalView(originalView);
|
||||
setIconAndDotVisible(originalView, false);
|
||||
} else {
|
||||
mIconLoadResult.onIconLoaded = () -> {
|
||||
if (cancellationSignal.isCanceled()) {
|
||||
|
@ -392,22 +369,13 @@ public class FloatingIconView extends FrameLayout implements
|
|||
mIconLoadResult.iconOffset);
|
||||
|
||||
setVisibility(VISIBLE);
|
||||
hideOriginalView(originalView);
|
||||
setIconAndDotVisible(originalView, false);
|
||||
};
|
||||
mLoadIconSignal = cancellationSignal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void hideOriginalView(View originalView) {
|
||||
if (originalView instanceof IconLabelDotView) {
|
||||
((IconLabelDotView) originalView).setIconVisible(false);
|
||||
((IconLabelDotView) originalView).setForceHideDot(true);
|
||||
} else {
|
||||
originalView.setVisibility(INVISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
@SuppressWarnings("WrongThread")
|
||||
private static int getOffsetForIconBounds(Launcher l, Drawable drawable, RectF position) {
|
||||
|
@ -477,7 +445,7 @@ public class FloatingIconView extends FrameLayout implements
|
|||
}
|
||||
if (!mIsOpening) {
|
||||
// When closing an app, we want the item on the workspace to be invisible immediately
|
||||
hideOriginalView(mOriginalIcon);
|
||||
setIconAndDotVisible(mOriginalIcon, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -573,12 +541,7 @@ public class FloatingIconView extends FrameLayout implements
|
|||
|
||||
if (hideOriginal) {
|
||||
if (isOpening) {
|
||||
if (originalView instanceof BubbleTextView) {
|
||||
((BubbleTextView) originalView).setIconVisible(true);
|
||||
((BubbleTextView) originalView).setForceHideDot(false);
|
||||
} else {
|
||||
originalView.setVisibility(VISIBLE);
|
||||
}
|
||||
setIconAndDotVisible(originalView, true);
|
||||
view.finish(dragLayer);
|
||||
} else {
|
||||
view.mFadeAnimatorSet = view.createFadeAnimation(originalView, dragLayer);
|
||||
|
@ -615,12 +578,10 @@ public class FloatingIconView extends FrameLayout implements
|
|||
});
|
||||
|
||||
if (originalView instanceof IconLabelDotView) {
|
||||
IconLabelDotView view = (IconLabelDotView) originalView;
|
||||
fade.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
view.setIconVisible(true);
|
||||
view.setForceHideDot(false);
|
||||
setIconAndDotVisible(originalView, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -15,10 +15,24 @@
|
|||
*/
|
||||
package com.android.launcher3.views;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
/**
|
||||
* A view that has an icon, label, and notification dot.
|
||||
*/
|
||||
public interface IconLabelDotView {
|
||||
void setIconVisible(boolean visible);
|
||||
void setForceHideDot(boolean hide);
|
||||
|
||||
/**
|
||||
* Sets the visibility of icon and dot of the view
|
||||
*/
|
||||
static void setIconAndDotVisible(View view, boolean visible) {
|
||||
if (view instanceof IconLabelDotView) {
|
||||
((IconLabelDotView) view).setIconVisible(visible);
|
||||
((IconLabelDotView) view).setForceHideDot(!visible);
|
||||
} else {
|
||||
view.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -220,7 +220,7 @@ public class OptionsPopupView extends ArrowPopup
|
|||
if (!TextUtils.isEmpty(pickerPackage)) {
|
||||
intent.setPackage(pickerPackage);
|
||||
}
|
||||
return launcher.startActivitySafely(v, intent, dummyInfo(intent), null);
|
||||
return launcher.startActivitySafely(v, intent, dummyInfo(intent));
|
||||
}
|
||||
|
||||
static WorkspaceItemInfo dummyInfo(Intent intent) {
|
||||
|
|
|
@ -20,8 +20,10 @@ import android.util.Log;
|
|||
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.icons.IconCache;
|
||||
import com.android.launcher3.model.data.PackageItemInfo;
|
||||
import com.android.launcher3.testing.TestProtocol;
|
||||
import com.android.launcher3.widget.WidgetsListAdapter.WidgetListRowEntryComparator;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -32,8 +34,8 @@ import java.util.Iterator;
|
|||
* methods accordingly.
|
||||
*/
|
||||
public class WidgetsDiffReporter {
|
||||
private static final boolean DEBUG = false;
|
||||
private static final String TAG = "WidgetsDiffReporter";
|
||||
private static final boolean DEBUG = Utilities.IS_RUNNING_IN_TEST_HARNESS; // b/160238801
|
||||
private static final String TAG = TestProtocol.NO_SCROLL_END_WIDGETS;
|
||||
|
||||
private final IconCache mIconCache;
|
||||
private final RecyclerView.Adapter mListener;
|
||||
|
|
|
@ -24,6 +24,7 @@ import android.animation.PropertyValuesHolder;
|
|||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
|
@ -38,8 +39,10 @@ import com.android.launcher3.Launcher;
|
|||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.LauncherAppWidgetHost.ProviderChangedListener;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.anim.PendingAnimation;
|
||||
import com.android.launcher3.compat.AccessibilityManagerCompat;
|
||||
import com.android.launcher3.testing.TestProtocol;
|
||||
import com.android.launcher3.views.RecyclerViewFastScroller;
|
||||
import com.android.launcher3.views.TopRoundedCornerView;
|
||||
|
||||
|
@ -68,6 +71,14 @@ public class WidgetsFullSheet extends BaseWidgetSheet
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchTouchEvent(MotionEvent ev) {
|
||||
if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
|
||||
Log.d(TestProtocol.NO_SCROLL_END_WIDGETS, "WidgetsFullSheet: " + ev);
|
||||
}
|
||||
return super.dispatchTouchEvent(ev);
|
||||
}
|
||||
|
||||
public WidgetsFullSheet(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
|
|
@ -120,6 +120,9 @@ public class WidgetsRecyclerView extends BaseRecyclerView implements OnItemTouch
|
|||
public int getCurrentScrollY() {
|
||||
// Skip early if widgets are not bound.
|
||||
if (isModelNotReady() || getChildCount() == 0) {
|
||||
if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
|
||||
Log.d(TestProtocol.NO_SCROLL_END_WIDGETS, "getCurrentScrollY: -1");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -128,6 +131,10 @@ public class WidgetsRecyclerView extends BaseRecyclerView implements OnItemTouch
|
|||
int y = (child.getMeasuredHeight() * rowIndex);
|
||||
int offset = getLayoutManager().getDecoratedTop(child);
|
||||
|
||||
if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
|
||||
Log.d(TestProtocol.NO_SCROLL_END_WIDGETS,
|
||||
"getCurrentScrollY: " + (getPaddingTop() + y - offset));
|
||||
}
|
||||
return getPaddingTop() + y - offset;
|
||||
}
|
||||
|
||||
|
@ -158,13 +165,23 @@ public class WidgetsRecyclerView extends BaseRecyclerView implements OnItemTouch
|
|||
mScrollbar.isHitInParent(e.getX(), e.getY(), mFastScrollerOffset);
|
||||
}
|
||||
if (mTouchDownOnScroller) {
|
||||
return mScrollbar.handleTouchEvent(e, mFastScrollerOffset);
|
||||
final boolean result = mScrollbar.handleTouchEvent(e, mFastScrollerOffset);
|
||||
if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
|
||||
Log.d(TestProtocol.NO_SCROLL_END_WIDGETS, "onInterceptTouchEvent 1 " + result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
|
||||
Log.d(TestProtocol.NO_SCROLL_END_WIDGETS, "onInterceptTouchEvent 2 false");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
|
||||
if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
|
||||
Log.d(TestProtocol.NO_SCROLL_END_WIDGETS, "WidgetsRecyclerView.onTouchEvent");
|
||||
}
|
||||
if (mTouchDownOnScroller) {
|
||||
mScrollbar.handleTouchEvent(e, mFastScrollerOffset);
|
||||
}
|
||||
|
@ -172,5 +189,31 @@ public class WidgetsRecyclerView extends BaseRecyclerView implements OnItemTouch
|
|||
|
||||
@Override
|
||||
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
|
||||
if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
|
||||
Log.d(TestProtocol.NO_SCROLL_END_WIDGETS, "onRequestDisallowInterceptTouchEvent "
|
||||
+ disallowIntercept);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchTouchEvent(MotionEvent ev) {
|
||||
final boolean result = super.dispatchTouchEvent(ev);
|
||||
if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
|
||||
Log.d(TestProtocol.NO_SCROLL_END_WIDGETS, "WidgetsRecyclerView: state: "
|
||||
+ getScrollState()
|
||||
+ " can scroll: " + getLayoutManager().canScrollVertically()
|
||||
+ " result: " + result
|
||||
+ " layout suppressed: " + isLayoutSuppressed()
|
||||
+ " event: " + ev);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopNestedScroll() {
|
||||
if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
|
||||
Log.d(TestProtocol.NO_SCROLL_END_WIDGETS, "stopNestedScroll");
|
||||
}
|
||||
super.stopNestedScroll();
|
||||
}
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.systemui.plugins;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.os.UserHandle;
|
||||
|
||||
import com.android.systemui.plugins.annotations.ProvidesInterface;
|
||||
|
||||
/**
|
||||
* Plugin interface which sends app launch events.
|
||||
*/
|
||||
@ProvidesInterface(action = AppLaunchEventsPlugin.ACTION, version = AppLaunchEventsPlugin.VERSION)
|
||||
public interface AppLaunchEventsPlugin extends Plugin {
|
||||
String ACTION = "com.android.systemui.action.PLUGIN_APP_EVENTS";
|
||||
int VERSION = 1;
|
||||
|
||||
/**
|
||||
* Receives onStartShortcut event from
|
||||
* {@link com.android.launcher3.appprediction.PredictionAppTracker}.
|
||||
*/
|
||||
void onStartShortcut(String packageName, String shortcutId, UserHandle user, String container);
|
||||
|
||||
/**
|
||||
* Receives onStartApp event from
|
||||
* {@link com.android.launcher3.appprediction.PredictionAppTracker}.
|
||||
*/
|
||||
void onStartApp(ComponentName componentName, UserHandle user, String container);
|
||||
|
||||
/**
|
||||
* Receives onDismissApp event from
|
||||
* {@link com.android.launcher3.appprediction.PredictionAppTracker}.
|
||||
*/
|
||||
void onDismissApp(ComponentName componentName, UserHandle user, String container);
|
||||
|
||||
/**
|
||||
* Receives onReturnedToHome event from
|
||||
* {@link com.android.launcher3.appprediction.PredictionAppTracker}.
|
||||
*/
|
||||
void onReturnedToHome();
|
||||
}
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
<receiver
|
||||
android:name="com.android.launcher3.testcomponent.AppWidgetNoConfig"
|
||||
android:exported="true"
|
||||
android:label="No Config">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
|
||||
|
@ -39,6 +40,7 @@
|
|||
|
||||
<receiver
|
||||
android:name="com.android.launcher3.testcomponent.AppWdigetHidden"
|
||||
android:exported="true"
|
||||
android:label="Hidden widget">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
|
||||
|
@ -49,6 +51,7 @@
|
|||
|
||||
<receiver
|
||||
android:name="com.android.launcher3.testcomponent.AppWidgetWithConfig"
|
||||
android:exported="true"
|
||||
android:label="With Config">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
|
||||
|
@ -58,12 +61,14 @@
|
|||
</receiver>
|
||||
|
||||
<activity
|
||||
android:name="com.android.launcher3.testcomponent.WidgetConfigActivity">
|
||||
android:name="com.android.launcher3.testcomponent.WidgetConfigActivity"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name="com.android.launcher3.testcomponent.CustomShortcutConfigActivity">
|
||||
<activity android:name="com.android.launcher3.testcomponent.CustomShortcutConfigActivity"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.CREATE_SHORTCUT" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
|
@ -72,6 +77,7 @@
|
|||
<activity
|
||||
android:name="com.android.launcher3.testcomponent.RequestPinItemActivity"
|
||||
android:icon="@drawable/test_drawable_pin_item"
|
||||
android:exported="true"
|
||||
android:label="Test Pin Item">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
|
@ -102,6 +108,7 @@
|
|||
android:stateNotNeeded="true"
|
||||
android:taskAffinity=""
|
||||
android:theme="@android:style/Theme.DeviceDefault.Light"
|
||||
android:exported="true"
|
||||
android:windowSoftInputMode="adjustPan">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
|
@ -114,6 +121,7 @@
|
|||
<activity
|
||||
android:name="com.android.launcher3.testcomponent.BaseTestingActivity"
|
||||
android:label="LauncherTestApp"
|
||||
android:exported="true"
|
||||
android:taskAffinity="com.android.launcher3.testcomponent.Affinity1">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
|
@ -128,6 +136,7 @@
|
|||
</activity>
|
||||
<activity-alias android:name="Activity2"
|
||||
android:label="TestActivity2"
|
||||
android:exported="true"
|
||||
android:targetActivity="com.android.launcher3.testcomponent.BaseTestingActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
|
@ -136,6 +145,7 @@
|
|||
</activity-alias>
|
||||
<activity-alias android:name="Activity3"
|
||||
android:label="TestActivity3"
|
||||
android:exported="true"
|
||||
android:targetActivity="com.android.launcher3.testcomponent.BaseTestingActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
|
@ -144,6 +154,7 @@
|
|||
</activity-alias>
|
||||
<activity-alias android:name="Activity4"
|
||||
android:label="TestActivity4"
|
||||
android:exported="true"
|
||||
android:targetActivity="com.android.launcher3.testcomponent.BaseTestingActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
|
@ -152,6 +163,7 @@
|
|||
</activity-alias>
|
||||
<activity-alias android:name="Activity5"
|
||||
android:label="TestActivity5"
|
||||
android:exported="true"
|
||||
android:targetActivity="com.android.launcher3.testcomponent.BaseTestingActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
|
@ -160,6 +172,7 @@
|
|||
</activity-alias>
|
||||
<activity-alias android:name="Activity6"
|
||||
android:label="TestActivity6"
|
||||
android:exported="true"
|
||||
android:targetActivity="com.android.launcher3.testcomponent.BaseTestingActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
|
@ -168,6 +181,7 @@
|
|||
</activity-alias>
|
||||
<activity-alias android:name="Activity7"
|
||||
android:label="TestActivity7"
|
||||
android:exported="true"
|
||||
android:targetActivity="com.android.launcher3.testcomponent.BaseTestingActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
|
@ -176,6 +190,7 @@
|
|||
</activity-alias>
|
||||
<activity-alias android:name="Activity8"
|
||||
android:label="TestActivity8"
|
||||
android:exported="true"
|
||||
android:targetActivity="com.android.launcher3.testcomponent.BaseTestingActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
|
@ -184,6 +199,7 @@
|
|||
</activity-alias>
|
||||
<activity-alias android:name="Activity9"
|
||||
android:label="TestActivity9"
|
||||
android:exported="true"
|
||||
android:targetActivity="com.android.launcher3.testcomponent.BaseTestingActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
|
@ -192,6 +208,7 @@
|
|||
</activity-alias>
|
||||
<activity-alias android:name="Activity10"
|
||||
android:label="TestActivity10"
|
||||
android:exported="true"
|
||||
android:targetActivity="com.android.launcher3.testcomponent.BaseTestingActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
|
@ -200,6 +217,7 @@
|
|||
</activity-alias>
|
||||
<activity-alias android:name="Activity11"
|
||||
android:label="TestActivity11"
|
||||
android:exported="true"
|
||||
android:targetActivity="com.android.launcher3.testcomponent.BaseTestingActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
<activity
|
||||
android:name="Activity1"
|
||||
android:icon="@mipmap/ic_launcher1"
|
||||
android:exported="true"
|
||||
android:label="Aardwolf">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
|
|
|
@ -73,20 +73,12 @@ public class ActivityLeakTracker implements Application.ActivityLifecycleCallbac
|
|||
}
|
||||
|
||||
public boolean noLeakedActivities() {
|
||||
int liveActivities = 0;
|
||||
int destroyedActivities = 0;
|
||||
|
||||
for (Activity activity : mActivities.keySet()) {
|
||||
if (activity.isDestroyed()) {
|
||||
++destroyedActivities;
|
||||
} else {
|
||||
++liveActivities;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (liveActivities > 2) return false;
|
||||
|
||||
// It's OK to have 1 leaked activity if no active activities exist.
|
||||
return liveActivities == 0 ? destroyedActivities <= 1 : destroyedActivities == 0;
|
||||
return mActivities.size() <= 2;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -152,6 +152,7 @@ public final class LauncherInstrumentation {
|
|||
private static final String WIDGETS_RES_ID = "widgets_list_view";
|
||||
private static final String CONTEXT_MENU_RES_ID = "deep_shortcuts_container";
|
||||
public static final int WAIT_TIME_MS = 10000;
|
||||
public static final int LONG_WAIT_TIME_MS = 60000;
|
||||
private static final String SYSTEMUI_PACKAGE = "com.android.systemui";
|
||||
|
||||
private static WeakReference<VisibleContainer> sActiveContainer = new WeakReference<>(null);
|
||||
|
@ -635,9 +636,11 @@ public final class LauncherInstrumentation {
|
|||
Parcelable executeAndWaitForEvent(Runnable command,
|
||||
UiAutomation.AccessibilityEventFilter eventFilter, Supplier<String> message) {
|
||||
try {
|
||||
Log.d(TestProtocol.NO_SCROLL_END_WIDGETS, "executeAndWaitForEvent: before");
|
||||
final AccessibilityEvent event =
|
||||
mInstrumentation.getUiAutomation().executeAndWaitForEvent(
|
||||
command, eventFilter, WAIT_TIME_MS);
|
||||
command, eventFilter, LONG_WAIT_TIME_MS);
|
||||
Log.d(TestProtocol.NO_SCROLL_END_WIDGETS, "executeAndWaitForEvent: after");
|
||||
assertNotNull("executeAndWaitForEvent returned null (this can't happen)", event);
|
||||
final Parcelable parcelableData = event.getParcelableData();
|
||||
event.recycle();
|
||||
|
@ -1094,7 +1097,10 @@ public final class LauncherInstrumentation {
|
|||
executeAndWaitForEvent(
|
||||
() -> linearGesture(
|
||||
startX, startY, endX, endY, steps, slowDown, GestureScope.INSIDE),
|
||||
event -> TestProtocol.SCROLL_FINISHED_MESSAGE.equals(event.getClassName()),
|
||||
event -> {
|
||||
Log.d(TestProtocol.NO_SCROLL_END_WIDGETS, "scroll: received event: " + event);
|
||||
return TestProtocol.SCROLL_FINISHED_MESSAGE.equals(event.getClassName());
|
||||
},
|
||||
() -> "Didn't receive a scroll end message: " + startX + ", " + startY
|
||||
+ ", " + endX + ", " + endY);
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue