Snap for 5892445 from 1cfbdcec9b to rvc-release

Change-Id: Ia3983064252d6a99da280ca214233aee1f5433a2
This commit is contained in:
android-build-team Robot
2019-09-21 23:25:03 +00:00
252 changed files with 4470 additions and 2894 deletions
+5 -15
View File
@@ -23,12 +23,7 @@ include $(CLEAR_VARS)
LOCAL_USE_AAPT2 := true
LOCAL_AAPT2_ONLY := true
LOCAL_MODULE_TAGS := optional
ifneq (,$(wildcard frameworks/base))
LOCAL_STATIC_JAVA_LIBRARIES:= PluginCoreLib
else
LOCAL_STATIC_JAVA_LIBRARIES:= libPluginCore
endif
LOCAL_STATIC_JAVA_LIBRARIES:= PluginCoreLib
LOCAL_SRC_FILES := \
$(call all-java-files-under, src_plugins)
@@ -89,8 +84,7 @@ LOCAL_STATIC_ANDROID_LIBRARIES := \
LOCAL_SRC_FILES := \
$(call all-java-files-under, src) \
$(call all-java-files-under, src_shortcuts_overrides) \
$(call all-java-files-under, src_ui_overrides) \
$(call all-java-files-under, src_flags)
$(call all-java-files-under, src_ui_overrides)
LOCAL_PROGUARD_FLAG_FILES := proguard.flags
# Proguard is disable for testing. Derivarive prjects to keep proguard enabled
@@ -151,11 +145,10 @@ LOCAL_USE_AAPT2 := true
LOCAL_AAPT2_ONLY := true
LOCAL_MODULE_TAGS := optional
LOCAL_STATIC_JAVA_LIBRARIES := SystemUISharedLib launcherprotosnano
ifneq (,$(wildcard frameworks/base))
LOCAL_STATIC_JAVA_LIBRARIES := SystemUISharedLib launcherprotosnano
LOCAL_PRIVATE_PLATFORM_APIS := true
else
LOCAL_STATIC_JAVA_LIBRARIES := libSharedSystemUI libLauncherProtos
LOCAL_SDK_VERSION := system_current
LOCAL_MIN_SDK_VERSION := 26
endif
@@ -169,7 +162,6 @@ LOCAL_SRC_FILES := \
$(call all-java-files-under, src) \
$(call all-java-files-under, quickstep/src) \
$(call all-java-files-under, quickstep/recents_ui_overrides/src) \
$(call all-java-files-under, src_flags) \
$(call all-java-files-under, src_shortcuts_overrides)
LOCAL_RESOURCE_DIR := \
@@ -224,11 +216,10 @@ include $(CLEAR_VARS)
LOCAL_USE_AAPT2 := true
LOCAL_MODULE_TAGS := optional
LOCAL_STATIC_JAVA_LIBRARIES := SystemUISharedLib launcherprotosnano
ifneq (,$(wildcard frameworks/base))
LOCAL_STATIC_JAVA_LIBRARIES := SystemUISharedLib launcherprotosnano
LOCAL_PRIVATE_PLATFORM_APIS := true
else
LOCAL_STATIC_JAVA_LIBRARIES := libSharedSystemUI libLauncherProtos
LOCAL_SDK_VERSION := system_current
LOCAL_MIN_SDK_VERSION := 26
endif
@@ -271,11 +262,10 @@ include $(CLEAR_VARS)
LOCAL_USE_AAPT2 := true
LOCAL_MODULE_TAGS := optional
LOCAL_STATIC_JAVA_LIBRARIES := SystemUISharedLib launcherprotosnano
ifneq (,$(wildcard frameworks/base))
LOCAL_STATIC_JAVA_LIBRARIES := SystemUISharedLib launcherprotosnano
LOCAL_PRIVATE_PLATFORM_APIS := true
else
LOCAL_STATIC_JAVA_LIBRARIES := libSharedSystemUI libLauncherProtos
LOCAL_SDK_VERSION := system_current
LOCAL_MIN_SDK_VERSION := 26
endif
+2
View File
@@ -0,0 +1,2 @@
[Hook Scripts]
checkstyle_hook = ${REPO_ROOT}/prebuilts/checkstyle/checkstyle.py --sha ${PREUPLOAD_COMMIT}
@@ -20,7 +20,6 @@ import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherStateManager.StateHandler;
import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.graphics.RotationMode;
import com.android.launcher3.uioverrides.touchcontrollers.LandscapeEdgeSwipeController;
import com.android.launcher3.uioverrides.touchcontrollers.LandscapeStatesTouchController;
@@ -51,7 +50,7 @@ public abstract class RecentsUiFactory {
.getMode().hasGestures;
list.add(new PortraitStatesTouchController(launcher, allowDragToOverview));
}
if (FeatureFlags.PULL_DOWN_STATUS_BAR && Utilities.IS_DEBUG_DEVICE
if (Utilities.IS_DEBUG_DEVICE
&& !launcher.getDeviceProfile().isMultiWindowMode
&& !launcher.getDeviceProfile().isVerticalBarLayout()) {
list.add(new StatusBarTouchController(launcher));
@@ -15,8 +15,8 @@
*/
package com.android.quickstep;
import static com.android.systemui.shared.system.ActivityManagerWrapper
.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
import android.annotation.TargetApi;
import android.content.Context;
@@ -25,7 +25,6 @@ import android.os.SystemClock;
import android.view.ViewConfiguration;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.logging.UserEventDispatcher;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.quickstep.ActivityControlHelper.ActivityInitListener;
@@ -43,7 +42,6 @@ public class OverviewCommandHelper {
private final Context mContext;
private final ActivityManagerWrapper mAM;
private final RecentsModel mRecentsModel;
private final MainThreadExecutor mMainThreadExecutor;
private final OverviewComponentObserver mOverviewComponentObserver;
private long mLastToggleTime;
@@ -51,7 +49,6 @@ public class OverviewCommandHelper {
public OverviewCommandHelper(Context context, OverviewComponentObserver observer) {
mContext = context;
mAM = ActivityManagerWrapper.getInstance();
mMainThreadExecutor = new MainThreadExecutor();
mRecentsModel = RecentsModel.INSTANCE.get(mContext);
mOverviewComponentObserver = observer;
}
@@ -63,19 +60,19 @@ public class OverviewCommandHelper {
}
mAM.closeSystemWindows(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS);
mMainThreadExecutor.execute(new RecentsActivityCommand<>());
MAIN_EXECUTOR.execute(new RecentsActivityCommand<>());
}
public void onOverviewShown(boolean triggeredFromAltTab) {
mMainThreadExecutor.execute(new ShowRecentsCommand());
MAIN_EXECUTOR.execute(new ShowRecentsCommand());
}
public void onOverviewHidden() {
mMainThreadExecutor.execute(new HideRecentsCommand());
MAIN_EXECUTOR.execute(new HideRecentsCommand());
}
public void onTip(int actionType, int viewType) {
mMainThreadExecutor.execute(() ->
MAIN_EXECUTOR.execute(() ->
UserEventDispatcher.newInstance(mContext).logActionTip(actionType, viewType));
}
@@ -161,7 +158,7 @@ public class OverviewCommandHelper {
// Otherwise, start overview.
mListener = mHelper.createActivityInitListener(provider::onActivityReady);
mListener.registerAndStartActivity(mOverviewComponentObserver.getOverviewIntent(),
provider, mContext, mMainThreadExecutor.getHandler(),
provider, mContext, MAIN_EXECUTOR.getHandler(),
provider.getRecentsLaunchDuration());
}
@@ -34,8 +34,6 @@ import android.view.MotionEvent;
import com.android.launcher3.Utilities;
import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.util.LooperExecutor;
import com.android.launcher3.util.UiThreadHelper;
import com.android.systemui.shared.recents.IOverviewProxy;
import com.android.systemui.shared.recents.ISystemUiProxy;
@@ -139,9 +137,6 @@ public class TouchInteractionService extends Service {
return sConnected;
}
public static final LooperExecutor BACKGROUND_EXECUTOR =
new LooperExecutor(UiThreadHelper.getBackgroundLooper());
private RecentsModel mRecentsModel;
private OverviewComponentObserver mOverviewComponentObserver;
private OverviewCommandHelper mOverviewCommandHelper;
@@ -1,32 +0,0 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.launcher3.config;
import android.content.Context;
/**
* Defines a set of flags used to control various launcher behaviors
*/
public final class FeatureFlags extends BaseFlags {
private FeatureFlags() {
// Prevent instantiation
}
// Features to control Launcher3Go behavior
public static final boolean GO_DISABLE_WIDGETS = true;
public static final boolean LAUNCHER3_SPRING_ICONS = false;
}
@@ -16,9 +16,8 @@
package com.android.launcher3.model;
import com.android.launcher3.AllAppsList;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherModel.Callbacks;
import com.android.launcher3.model.BgDataModel.Callbacks;
import java.lang.ref.WeakReference;
@@ -37,6 +37,10 @@ import androidx.annotation.Nullable;
* <p> The widgets and shortcuts are organized using package name as its index.
*/
public class WidgetsModel {
// True is the widget support is disabled.
public static final boolean GO_DISABLE_WIDGETS = false;
private static final ArrayList<WidgetListRowEntry> EMPTY_WIDGET_LIST = new ArrayList<>();
/**
@@ -27,34 +27,23 @@ import android.os.UserHandle;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.notification.NotificationKeyData;
import java.util.Collections;
import java.util.ArrayList;
import java.util.List;
/**
* Performs operations related to deep shortcuts, such as querying for them, pinning them, etc.
*/
public class DeepShortcutManager {
private static DeepShortcutManager sInstance;
private static final Object sInstanceLock = new Object();
private static final DeepShortcutManager sInstance = new DeepShortcutManager();
public static DeepShortcutManager getInstance(Context context) {
synchronized (sInstanceLock) {
if (sInstance == null) {
sInstance = new DeepShortcutManager(context.getApplicationContext());
}
return sInstance;
}
return sInstance;
}
private DeepShortcutManager(Context context) {
}
private final QueryResult mFailure = new QueryResult();
public boolean wasLastCallSuccess() {
return false;
}
public void onShortcutsChanged(List<ShortcutInfo> shortcuts) {
}
private DeepShortcutManager() { }
/**
* Queries for the shortcuts with the package name and provided ids.
@@ -62,18 +51,18 @@ public class DeepShortcutManager {
* This method is intended to get the full details for shortcuts when they are added or updated,
* because we only get "key" fields in onShortcutsChanged().
*/
public List<ShortcutInfo> queryForFullDetails(String packageName,
public QueryResult queryForFullDetails(String packageName,
List<String> shortcutIds, UserHandle user) {
return Collections.emptyList();
return mFailure;
}
/**
* Gets all the manifest and dynamic shortcuts associated with the given package and user,
* to be displayed in the shortcuts container on long press.
*/
public List<ShortcutInfo> queryForShortcutsContainer(ComponentName activity,
public QueryResult queryForShortcutsContainer(ComponentName activity,
UserHandle user) {
return Collections.emptyList();
return mFailure;
}
/**
@@ -103,20 +92,28 @@ public class DeepShortcutManager {
*
* If packageName is null, returns all pinned shortcuts regardless of package.
*/
public List<ShortcutInfo> queryForPinnedShortcuts(String packageName, UserHandle user) {
return Collections.emptyList();
public QueryResult queryForPinnedShortcuts(String packageName, UserHandle user) {
return mFailure;
}
public List<ShortcutInfo> queryForPinnedShortcuts(String packageName,
public QueryResult queryForPinnedShortcuts(String packageName,
List<String> shortcutIds, UserHandle user) {
return Collections.emptyList();
return mFailure;
}
public List<ShortcutInfo> queryForAllShortcuts(UserHandle user) {
return Collections.emptyList();
public QueryResult queryForAllShortcuts(UserHandle user) {
return mFailure;
}
public boolean hasHostPermission() {
return false;
}
public static class QueryResult extends ArrayList<ShortcutInfo> {
public boolean wasSuccess() {
return true;
}
}
}
+1 -1
View File
@@ -10,4 +10,4 @@ PROTOBUF_CLASS_PATH=com.google.protobuf:protobuf-gradle-plugin:0.8.6
PROTOBUF_DEPENDENCY=com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-7
BUILD_TOOLS_VERSION=28.0.3
COMPILE_SDK=android-Q
COMPILE_SDK=android-R
@@ -267,6 +267,10 @@ public abstract class BaseIconCache {
entry = new CacheEntry();
cachingLogic.loadIcon(mContext, object, entry);
}
// Icon can't be loaded from cachingLogic, which implies alternative icon was loaded
// (e.g. fallback icon, default icon). So we drop here since there's no point in caching
// an empty entry.
if (entry.icon == null) return;
entry.title = cachingLogic.getLabel(object);
entry.contentDescription = mPackageManager.getUserBadgedLabel(entry.title, user);
mCache.put(key, entry);
@@ -17,6 +17,7 @@ package com.android.launcher3.icons.cache;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.os.LocaleList;
import android.os.UserHandle;
@@ -41,4 +42,11 @@ public interface CachingLogic<T> {
default String getKeywords(T object, LocaleList localeList) {
return null;
}
/**
* Returns the timestamp the entry was last updated in cache.
*/
default long getLastUpdatedTime(T object, PackageInfo info) {
return info.lastUpdateTime;
}
}
@@ -171,8 +171,9 @@ public class IconCacheUpdateHandler {
long updateTime = c.getLong(indexLastUpdate);
int version = c.getInt(indexVersion);
T app = componentMap.remove(component);
if (version == info.versionCode && updateTime == info.lastUpdateTime &&
TextUtils.equals(c.getString(systemStateIndex),
if (version == info.versionCode
&& updateTime == cachingLogic.getLastUpdatedTime(app, info)
&& TextUtils.equals(c.getString(systemStateIndex),
mIconCache.getIconSystemState(info.packageName))) {
if (mFilterMode == MODE_CLEAR_VALID_ITEMS) {
@@ -231,7 +232,6 @@ public class IconCacheUpdateHandler {
}
}
/**
* A runnable that updates invalid icons and adds missing icons in the DB for the provided
* LauncherActivityInfo list. Items are updated/added one at a time, so that the
+1
View File
@@ -118,6 +118,7 @@ enum ControlType {
APP_USAGE_SETTINGS = 18;
BACK_GESTURE = 19;
UNDO = 20;
DISMISS_PREDICTION = 21;
}
enum TipType {
@@ -17,6 +17,8 @@ package com.android.launcher3.appprediction;
import static android.content.pm.PackageManager.MATCH_INSTANT;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
@@ -30,8 +32,12 @@ import android.os.Message;
import android.util.ArrayMap;
import android.util.Log;
import androidx.annotation.MainThread;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
import androidx.annotation.WorkerThread;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherModel;
import com.android.launcher3.WorkspaceItemInfo;
import com.android.launcher3.icons.IconCache;
import com.android.launcher3.icons.LauncherIcons;
@@ -45,11 +51,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import androidx.annotation.MainThread;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
import androidx.annotation.WorkerThread;
/**
* Utility class which loads and caches predicted items like instant apps and shortcuts, before
* they can be displayed on the UI
@@ -77,7 +78,7 @@ public class DynamicItemCache {
public DynamicItemCache(Context context, Runnable onUpdateCallback) {
mContext = context;
mWorker = new Handler(LauncherModel.getWorkerLooper(), this::handleWorkerMessage);
mWorker = new Handler(MODEL_EXECUTOR.getLooper(), this::handleWorkerMessage);
mUiHandler = new Handler(Looper.getMainLooper(), this::handleUiMessage);
mInstantAppResolver = InstantAppResolver.newInstance(context);
mOnUpdateCallback = onUpdateCallback;
@@ -1,4 +1,4 @@
/**
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,6 +16,7 @@
package com.android.launcher3.appprediction;
import static com.android.launcher3.InvariantDeviceProfile.CHANGE_FLAG_GRID;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import android.annotation.TargetApi;
import android.app.prediction.AppPredictionContext;
@@ -34,19 +35,25 @@ import android.os.UserHandle;
import android.util.Log;
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.model.AppLaunchTracker;
import com.android.launcher3.util.UiThreadHelper;
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
import com.android.systemui.plugins.AppLaunchEventsPlugin;
import com.android.systemui.plugins.PluginListener;
import androidx.annotation.UiThread;
import androidx.annotation.WorkerThread;
import java.util.ArrayList;
import java.util.List;
/**
* 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 {
public class PredictionAppTracker extends AppLaunchTracker
implements PluginListener<AppLaunchEventsPlugin> {
private static final String TAG = "PredictionAppTracker";
private static final boolean DBG = false;
@@ -58,6 +65,7 @@ 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;
@@ -65,10 +73,14 @@ public class PredictionAppTracker extends AppLaunchTracker {
public PredictionAppTracker(Context context) {
mContext = context;
mMessageHandler = new Handler(UiThreadHelper.getBackgroundLooper(), this::handleMessage);
mMessageHandler = new Handler(UI_HELPER_EXECUTOR.getLooper(), this::handleMessage);
InvariantDeviceProfile.INSTANCE.get(mContext).addOnChangeListener(this::onIdpChanged);
mMessageHandler.sendEmptyMessage(MSG_INIT);
mAppLaunchEventsPluginsList = new ArrayList<>();
PluginManagerWrapper.INSTANCE.get(context)
.addPluginListener(this, AppLaunchEventsPlugin.class, true);
}
@UiThread
@@ -96,7 +108,7 @@ public class PredictionAppTracker extends AppLaunchTracker {
AppPredictionManager apm = mContext.getSystemService(AppPredictionManager.class);
if (apm == null) {
return null;
return null;
}
AppPredictor predictor = apm.createAppPredictionSession(
@@ -116,7 +128,7 @@ public class PredictionAppTracker extends AppLaunchTracker {
*/
@WorkerThread
@Nullable
public Bundle getAppPredictionContextExtras(Client client){
public Bundle getAppPredictionContextExtras(Client client) {
return null;
}
@@ -128,7 +140,7 @@ public class PredictionAppTracker extends AppLaunchTracker {
destroy();
// Initialize the clients
int count = InvariantDeviceProfile.INSTANCE.get(mContext).numColumns;
int count = InvariantDeviceProfile.INSTANCE.get(mContext).numAllAppsColumns;
mHomeAppPredictor = createPredictor(Client.HOME, count);
mRecentsOverviewPredictor = createPredictor(Client.OVERVIEW, count);
return true;
@@ -167,37 +179,98 @@ 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) {
String container) {
// TODO: Use the full shortcut info
AppTarget target = new AppTarget
.Builder(new AppTargetId("shortcut:" + shortcutId), packageName, user)
.setClassName(shortcutId)
.build();
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();
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
private void sendLaunch(AppTarget target, String container) {
AppTargetEvent event = new AppTargetEvent.Builder(target, AppTargetEvent.ACTION_LAUNCH)
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) {
AppTargetEvent event = new AppTargetEvent.Builder(target, eventId)
.setLaunchLocation(container == null ? CONTAINER_DEFAULT : container)
.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);
}
@Override
public void onPluginDisconnected(AppLaunchEventsPlugin appLaunchEventsPlugin) {
mAppLaunchEventsPluginsList.remove(appLaunchEventsPlugin);
}
}
@@ -43,6 +43,7 @@ import com.android.launcher3.ItemInfo;
import com.android.launcher3.ItemInfoWithIcon;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.R;
import com.android.launcher3.WorkspaceItemInfo;
import com.android.launcher3.allapps.AllAppsStore;
@@ -92,7 +93,7 @@ public class PredictionRowView extends LinearLayout implements
private final Launcher mLauncher;
private final PredictionUiStateManager mPredictionUiStateManager;
private final int mNumPredictedAppsPerRow;
private int mNumPredictedAppsPerRow;
// The set of predicted app component names
private final List<ComponentKeyMapper> mPredictedAppComponents = new ArrayList<>();
@@ -128,7 +129,7 @@ public class PredictionRowView extends LinearLayout implements
mFocusHelper = new SimpleFocusIndicatorHelper(this);
mNumPredictedAppsPerRow = LauncherAppState.getIDP(context).numColumns;
mNumPredictedAppsPerRow = LauncherAppState.getIDP(context).numAllAppsColumns;
mLauncher = Launcher.getLauncher(context);
mLauncher.addOnDeviceProfileChangeListener(this);
@@ -226,6 +227,7 @@ public class PredictionRowView extends LinearLayout implements
@Override
public void onDeviceProfileChanged(DeviceProfile dp) {
mNumPredictedAppsPerRow = dp.inv.numAllAppsColumns;
removeAllViews();
applyPredictionApps();
}
@@ -281,7 +283,7 @@ public class PredictionRowView extends LinearLayout implements
}
private List<ItemInfoWithIcon> processPredictedAppComponents(List<ComponentKeyMapper> components) {
if (getAppsStore().getApps().isEmpty()) {
if (getAppsStore().getApps().length == 0) {
// Apps have not been bound yet.
return Collections.emptyList();
}
@@ -290,7 +292,9 @@ public class PredictionRowView extends LinearLayout implements
for (ComponentKeyMapper mapper : components) {
ItemInfoWithIcon info = mapper.getApp(getAppsStore());
if (info != null) {
predictedApps.add(info);
ItemInfoWithIcon predictedApp = info.clone();
predictedApp.container = LauncherSettings.Favorites.CONTAINER_PREDICTION;
predictedApps.add(predictedApp);
} else {
if (FeatureFlags.IS_DOGFOOD_BUILD) {
Log.e(TAG, "Predicted app not found: " + mapper);
@@ -28,17 +28,15 @@ import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.LauncherStateManager.StateHandler;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.graphics.RotationMode;
import com.android.launcher3.uioverrides.touchcontrollers.FlingAndHoldTouchController;
import com.android.launcher3.uioverrides.touchcontrollers.LandscapeEdgeSwipeController;
import com.android.launcher3.uioverrides.touchcontrollers.NavBarToHomeTouchController;
import com.android.launcher3.uioverrides.touchcontrollers.OverviewToAllAppsTouchController;
import com.android.launcher3.uioverrides.touchcontrollers.PortraitStatesTouchController;
import com.android.launcher3.uioverrides.touchcontrollers.StatusBarTouchController;
import com.android.launcher3.uioverrides.touchcontrollers.QuickSwitchTouchController;
import com.android.launcher3.uioverrides.touchcontrollers.StatusBarTouchController;
import com.android.launcher3.uioverrides.touchcontrollers.TaskViewTouchController;
import com.android.launcher3.uioverrides.touchcontrollers.TransposedQuickSwitchTouchController;
import com.android.launcher3.util.TouchController;
@@ -164,8 +162,7 @@ public abstract class RecentsUiFactory {
}
}
if (FeatureFlags.PULL_DOWN_STATUS_BAR
&& !launcher.getDeviceProfile().isMultiWindowMode) {
if (!launcher.getDeviceProfile().isMultiWindowMode) {
list.add(new StatusBarTouchController(launcher));
}
@@ -19,7 +19,6 @@ import static com.android.launcher3.LauncherAnimUtils.OVERVIEW_TRANSITION_MS;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.Launcher;
import com.android.launcher3.Utilities;
import com.android.launcher3.allapps.AllAppsTransitionController;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.quickstep.util.LayoutUtils;
@@ -69,8 +68,16 @@ public class BackgroundAppState extends OverviewState {
if (taskCount == 0) {
return super.getOverviewScaleAndTranslation(launcher);
}
TaskView dummyTask = recentsView.getTaskViewAt(Utilities.boundToRange(
recentsView.getCurrentPage(), 0, taskCount - 1));
TaskView dummyTask;
if (recentsView.getCurrentPage() >= 0) {
if (recentsView.getCurrentPage() <= taskCount - 1) {
dummyTask = recentsView.getCurrentPageTaskView();
} else {
dummyTask = recentsView.getTaskViewAt(taskCount - 1);
}
} else {
dummyTask = recentsView.getTaskViewAt(0);
}
return recentsView.getTempClipAnimationHelper().updateForFullscreenOverview(dummyTask)
.getScaleAndTranslation();
}
@@ -42,6 +42,7 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import com.android.launcher3.Launcher;
@@ -179,6 +180,11 @@ public class FlingAndHoldTouchController extends PortraitStatesTouchController {
} else {
super.onDragEnd(velocity, fling);
}
View searchView = mLauncher.getAppsView().getSearchView();
if (searchView instanceof FeedbackHandler) {
((FeedbackHandler) searchView).resetFeedback();
}
mMotionPauseDetector.clear();
}
@@ -205,4 +211,16 @@ public class FlingAndHoldTouchController extends PortraitStatesTouchController {
builder.addFlag(AnimatorSetBuilder.FLAG_DONT_ANIMATE_OVERVIEW);
}
}
/**
* Interface for views with feedback animation requiring reset
*/
public interface FeedbackHandler {
/**
* reset searchWidget feedback
*/
void resetFeedback();
}
}
@@ -47,9 +47,9 @@ public final class PortraitOverviewStateTouchHelper {
* @return true if we should intercept the motion event
*/
boolean canInterceptTouch(MotionEvent ev) {
if (mRecentsView.getChildCount() > 0) {
if (mRecentsView.getTaskViewCount() > 0) {
// Allow swiping up in the gap between the hotseat and overview.
return ev.getY() >= mRecentsView.getChildAt(0).getBottom();
return ev.getY() >= mRecentsView.getTaskViewAt(0).getBottom();
} else {
// If there are no tasks, we only intercept if we're below the hotseat height.
return isTouchOverHotseat(mLauncher, ev);
@@ -63,7 +63,7 @@ public final class PortraitOverviewStateTouchHelper {
* @return true if going back should take the user to the currently running task
*/
boolean shouldSwipeDownReturnToApp() {
TaskView taskView = mRecentsView.getTaskViewAt(mRecentsView.getNextPage());
TaskView taskView = mRecentsView.getNextPageTaskView();
return taskView != null && mRecentsView.shouldSwipeDownLaunchApp();
}
@@ -76,7 +76,7 @@ public final class PortraitOverviewStateTouchHelper {
*/
PendingAnimation createSwipeDownToTaskAppAnimation(long duration) {
mRecentsView.setCurrentPage(mRecentsView.getPageNearestToCenterOfScreen());
TaskView taskView = mRecentsView.getTaskViewAt(mRecentsView.getCurrentPage());
TaskView taskView = mRecentsView.getCurrentPageTaskView();
if (taskView == null) {
throw new IllegalStateException("There is no task view to animate to.");
}
@@ -50,7 +50,6 @@ import com.android.quickstep.SysUINavigationMode;
import com.android.quickstep.SysUINavigationMode.Mode;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.system.QuickStepContract;
/**
* Handles quick switching to a recent task from the home screen.
@@ -102,6 +102,7 @@ final class AppToOverviewAnimationProvider<T extends BaseDraggingActivity> imple
anim.addListener(new AnimationSuccessListener() {
@Override
public void onAnimationSuccess(Animator animator) {
mHelper.onSwipeUpToRecentsComplete(mActivity);
if (mRecentsView != null) {
mRecentsView.animateUpRunningTaskIconScale();
}
@@ -22,9 +22,9 @@ import static com.android.launcher3.Utilities.postAsyncCallback;
import static com.android.launcher3.anim.Interpolators.ACCEL_1_5;
import static com.android.launcher3.anim.Interpolators.DEACCEL;
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.Executors.UI_HELPER_EXECUTOR;
import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATION;
import static com.android.quickstep.TouchInteractionService.BACKGROUND_EXECUTOR;
import static com.android.quickstep.TouchInteractionService.MAIN_THREAD_EXECUTOR;
import static com.android.quickstep.TouchInteractionService.TOUCH_INTERACTION_LOG;
import android.animation.Animator;
@@ -44,9 +44,10 @@ import android.os.Vibrator;
import android.provider.Settings;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.view.animation.Interpolator;
import androidx.annotation.UiThread;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.InvariantDeviceProfile;
@@ -54,7 +55,6 @@ import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.graphics.RotationMode;
import com.android.launcher3.views.FloatingIconView;
import com.android.quickstep.ActivityControlHelper.ActivityInitListener;
@@ -75,8 +75,6 @@ import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
import java.util.function.Consumer;
import androidx.annotation.UiThread;
/**
* Base class for swipe up handler with some utility methods
*/
@@ -126,7 +124,7 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten
protected Runnable mGestureEndCallback;
protected final Handler mMainThreadHandler = MAIN_THREAD_EXECUTOR.getHandler();
protected final Handler mMainThreadHandler = MAIN_EXECUTOR.getHandler();
protected MultiStateCallback mStateCallback;
protected boolean mCanceled;
@@ -174,7 +172,7 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten
if (effect == null) {
return;
}
BACKGROUND_EXECUTOR.execute(() -> mVibrator.vibrate(effect));
UI_HELPER_EXECUTOR.execute(() -> mVibrator.vibrate(effect));
}
public Consumer<MotionEvent> getRecentsViewDispatcher(RotationMode rotationMode) {
@@ -229,10 +227,10 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten
// Launch the task user scrolled to (mRecentsView.getNextPage()).
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
// We finish recents animation inside launchTask() when live tile is enabled.
mRecentsView.getTaskViewAt(mRecentsView.getNextPage()).launchTask(false /* animate */,
mRecentsView.getNextPageTaskView().launchTask(false /* animate */,
true /* freezeTaskList */);
} else {
int taskId = mRecentsView.getTaskViewAt(mRecentsView.getNextPage()).getTask().key.id;
int taskId = mRecentsView.getNextPageTaskView().getTask().key.id;
mFinishingRecentsAnimationForNewTaskId = taskId;
mRecentsAnimationWrapper.finish(true /* toRecents */, () -> {
if (!mCanceled) {
@@ -275,7 +273,7 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten
overviewStackBounds = getStackBounds(dp);
}
dp.updateInsets(targetSet.homeContentInsets);
dp.updateIsSeascape(mContext.getSystemService(WindowManager.class));
dp.updateIsSeascape(mContext);
if (runningTaskTarget != null) {
mClipAnimationHelper.updateSource(overviewStackBounds, runningTaskTarget);
}
@@ -66,6 +66,7 @@ import com.android.quickstep.util.StaggeredWorkspaceAnim;
import com.android.quickstep.views.LauncherRecentsView;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
import com.android.systemui.plugins.shared.LauncherOverlayManager;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import java.util.function.BiPredicate;
@@ -268,7 +269,7 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe
INDEX_RECENTS_FADE_ANIM, attached ? 1 : 0);
int runningTaskIndex = recentsView.getRunningTaskIndex();
if (runningTaskIndex == 0) {
if (runningTaskIndex == recentsView.getTaskViewStartIndex()) {
// If we are on the first task (we haven't quick switched), translate recents in
// from the side. Calculate the start translation based on current scale/scroll.
float currScale = recentsView.getScaleX();
@@ -351,8 +352,7 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe
private void playScaleDownAnim(AnimatorSet anim, Launcher launcher, LauncherState fromState,
LauncherState endState) {
RecentsView recentsView = launcher.getOverviewPanel();
TaskView v = recentsView.getTaskViewAt(recentsView.getCurrentPage());
if (v == null) {
if (recentsView.getCurrentPageTaskView() == null) {
return;
}
@@ -380,7 +380,7 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe
// recents as a whole needs to translate further to keep up with the app window.
TaskView runningTaskView = recentsView.getRunningTaskView();
if (runningTaskView == null) {
runningTaskView = recentsView.getTaskViewAt(recentsView.getCurrentPage());
runningTaskView = recentsView.getCurrentPageTaskView();
}
TimeInterpolator oldInterpolator = translateY.getInterpolator();
Rect fallbackInsets = launcher.getDeviceProfile().getInsets();
@@ -479,4 +479,18 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe
public void onLaunchTaskSuccess(Launcher launcher) {
launcher.getStateManager().moveToRestState();
}
@Override
public void closeOverlay() {
Launcher launcher = getCreatedActivity();
if (launcher == null) {
return;
}
LauncherOverlayManager om = launcher.getOverlayManager();
if (!launcher.isStarted() || launcher.isForceInvisible()) {
om.hideOverlay(false /* animate */);
} else {
om.hideOverlay(150);
}
}
}
@@ -15,8 +15,8 @@
*/
package com.android.quickstep;
import static com.android.systemui.shared.system.ActivityManagerWrapper
.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -29,7 +29,6 @@ import android.util.Log;
import android.view.ViewConfiguration;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.logging.UserEventDispatcher;
import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.userevent.nano.LauncherLogProto;
@@ -49,7 +48,6 @@ public class OverviewCommandHelper {
private final Context mContext;
private final ActivityManagerWrapper mAM;
private final RecentsModel mRecentsModel;
private final MainThreadExecutor mMainThreadExecutor;
private final OverviewComponentObserver mOverviewComponentObserver;
private long mLastToggleTime;
@@ -57,7 +55,6 @@ public class OverviewCommandHelper {
public OverviewCommandHelper(Context context, OverviewComponentObserver observer) {
mContext = context;
mAM = ActivityManagerWrapper.getInstance();
mMainThreadExecutor = new MainThreadExecutor();
mRecentsModel = RecentsModel.INSTANCE.get(mContext);
mOverviewComponentObserver = observer;
}
@@ -69,19 +66,19 @@ public class OverviewCommandHelper {
}
mAM.closeSystemWindows(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS);
mMainThreadExecutor.execute(new RecentsActivityCommand<>());
MAIN_EXECUTOR.execute(new RecentsActivityCommand<>());
}
public void onOverviewShown(boolean triggeredFromAltTab) {
mMainThreadExecutor.execute(new ShowRecentsCommand(triggeredFromAltTab));
MAIN_EXECUTOR.execute(new ShowRecentsCommand(triggeredFromAltTab));
}
public void onOverviewHidden() {
mMainThreadExecutor.execute(new HideRecentsCommand());
MAIN_EXECUTOR.execute(new HideRecentsCommand());
}
public void onTip(int actionType, int viewType) {
mMainThreadExecutor.execute(() ->
MAIN_EXECUTOR.execute(() ->
UserEventDispatcher.newInstance(mContext).logActionTip(actionType, viewType));
}
@@ -112,7 +109,7 @@ public class OverviewCommandHelper {
TaskView taskView = rv.getNextTaskView();
if (taskView == null) {
if (rv.getTaskViewCount() > 0) {
taskView = (TaskView) rv.getPageAt(0);
taskView = rv.getTaskViewAt(0);
taskView.requestFocus();
} else {
rv.requestFocus();
@@ -183,7 +180,7 @@ public class OverviewCommandHelper {
// Otherwise, start overview.
mListener = mHelper.createActivityInitListener(this::onActivityReady);
mListener.registerAndStartActivity(mOverviewComponentObserver.getOverviewIntent(),
this::createWindowAnimation, mContext, mMainThreadExecutor.getHandler(),
this::createWindowAnimation, mContext, MAIN_EXECUTOR.getHandler(),
mAnimationProvider.getRecentsLaunchDuration());
}
@@ -1,9 +1,10 @@
package com.android.quickstep;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import android.content.Context;
import android.os.Bundle;
import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.testing.TestInformationHandler;
import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.uioverrides.states.OverviewState;
@@ -15,7 +16,9 @@ import java.util.concurrent.ExecutionException;
public class QuickstepTestInformationHandler extends TestInformationHandler {
private final Context mContext;
public QuickstepTestInformationHandler(Context context) {
mContext = context;
}
@Override
@@ -52,8 +55,8 @@ public class QuickstepTestInformationHandler extends TestInformationHandler {
case TestProtocol.REQUEST_OVERVIEW_LEFT_GESTURE_MARGIN: {
try {
final int leftMargin = new MainThreadExecutor().submit(() ->
mLauncher.<RecentsView>getOverviewPanel().getLeftGestureMargin()).get();
final int leftMargin = MAIN_EXECUTOR.submit(() ->
getRecentsView().getLeftGestureMargin()).get();
response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, leftMargin);
} catch (ExecutionException e) {
e.printStackTrace();
@@ -65,9 +68,8 @@ public class QuickstepTestInformationHandler extends TestInformationHandler {
case TestProtocol.REQUEST_OVERVIEW_RIGHT_GESTURE_MARGIN: {
try {
final int rightMargin = new MainThreadExecutor().submit(() ->
mLauncher.<RecentsView>getOverviewPanel().getRightGestureMargin()).
get();
final int rightMargin = MAIN_EXECUTOR.submit(() ->
getRecentsView().getRightGestureMargin()).get();
response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, rightMargin);
} catch (ExecutionException e) {
e.printStackTrace();
@@ -80,4 +82,13 @@ public class QuickstepTestInformationHandler extends TestInformationHandler {
return super.call(method);
}
private RecentsView getRecentsView() {
OverviewComponentObserver observer = new OverviewComponentObserver(mContext);
try {
return observer.getActivityControlHelper().getCreatedActivity().getOverviewPanel();
} finally {
observer.onDestroy();
}
}
}
@@ -135,6 +135,12 @@ public final class RecentsActivity extends BaseRecentsActivity {
return (T) mFallbackRecentsView;
}
@Override
public void returnToHomescreen() {
super.returnToHomescreen();
// TODO(b/137318995) This should go home, but doing so removes freeform windows
}
@Override
public ActivityOptions getActivityLaunchOptions(final View v) {
if (!(v instanceof TaskView)) {
@@ -15,7 +15,7 @@
*/
package com.android.quickstep;
import static com.android.quickstep.TouchInteractionService.MAIN_THREAD_EXECUTOR;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import android.util.Log;
@@ -25,6 +25,7 @@ import com.android.launcher3.util.Preconditions;
import com.android.quickstep.util.RecentsAnimationListenerSet;
import com.android.quickstep.util.SwipeAnimationTargetSet;
import com.android.quickstep.util.SwipeAnimationTargetSet.SwipeAnimationListener;
import java.io.PrintWriter;
/**
@@ -44,6 +45,7 @@ public class SwipeSharedState implements SwipeAnimationListener {
public boolean goingToLauncher;
public boolean recentsAnimationFinishInterrupted;
public int nextRunningTaskId = -1;
private int mLogId;
public void setOverviewComponentObserver(OverviewComponentObserver observer) {
mOverviewComponentObserver = observer;
@@ -77,7 +79,7 @@ public class SwipeSharedState implements SwipeAnimationListener {
mRecentsAnimationListener.removeListener(this);
mRecentsAnimationListener.cancelListener();
if (mLastAnimationRunning && mLastAnimationTarget != null) {
Utilities.postAsyncCallback(MAIN_THREAD_EXECUTOR.getHandler(),
Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(),
finishAnimation
? mLastAnimationTarget::finishAnimation
: mLastAnimationTarget::cancelAnimation);
@@ -155,5 +157,10 @@ public class SwipeSharedState implements SwipeAnimationListener {
pw.println(prefix + "nextRunningTaskId=" + nextRunningTaskId);
pw.println(prefix + "lastAnimationCancelled=" + mLastAnimationCancelled);
pw.println(prefix + "lastAnimationRunning=" + mLastAnimationRunning);
pw.println(prefix + "logTraceId=" + mLogId);
}
public void setLogTraceId(int logId) {
this.mLogId = logId;
}
}
@@ -36,8 +36,6 @@ import android.view.View;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
import com.android.launcher3.WorkspaceItemInfo;
import com.android.launcher3.popup.SystemShortcut;
@@ -267,12 +265,16 @@ public class TaskSystemShortcut<T extends SystemShortcut> extends SystemShortcut
@Override
protected ActivityOptions makeLaunchOptions(Activity activity) {
return ActivityOptionsCompat.makeFreeformOptions();
ActivityOptions activityOptions = ActivityOptionsCompat.makeFreeformOptions();
// Arbitrary bounds only because freeform is in dev mode right now
Rect r = new Rect(50, 50, 200, 200);
activityOptions.setLaunchBounds(r);
return activityOptions;
}
@Override
protected boolean onActivityStarted(BaseDraggingActivity activity) {
Launcher.getLauncher(activity).getStateManager().goToState(LauncherState.NORMAL);
activity.returnToHomescreen();
return true;
}
}
@@ -23,6 +23,8 @@ import static com.android.launcher3.config.FeatureFlags.ENABLE_HINTS_IN_OVERVIEW
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.launcher3.config.FeatureFlags.FAKE_LANDSCAPE_UI;
import static com.android.launcher3.config.FeatureFlags.QUICKSTEP_SPRINGS;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_INPUT_MONITOR;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SYSUI_PROXY;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_CLICKABLE;
@@ -50,8 +52,6 @@ import android.content.res.Configuration;
import android.graphics.Point;
import android.graphics.RectF;
import android.graphics.Region;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManager.DisplayListener;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
@@ -61,18 +61,15 @@ import android.os.RemoteException;
import android.text.TextUtils;
import android.util.Log;
import android.view.Choreographer;
import android.view.Display;
import android.view.InputEvent;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.WindowManager;
import androidx.annotation.BinderThread;
import androidx.annotation.UiThread;
import androidx.annotation.WorkerThread;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.R;
import com.android.launcher3.ResourceUtils;
import com.android.launcher3.Utilities;
@@ -82,8 +79,8 @@ import com.android.launcher3.logging.UserEventDispatcher;
import com.android.launcher3.model.AppLaunchTracker;
import com.android.launcher3.provider.RestoreDbTask;
import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.util.LooperExecutor;
import com.android.launcher3.util.UiThreadHelper;
import com.android.launcher3.uioverrides.DejankBinderTracker;
import com.android.launcher3.util.DefaultDisplay;
import com.android.quickstep.SysUINavigationMode.Mode;
import com.android.quickstep.SysUINavigationMode.NavigationModeChangeListener;
import com.android.quickstep.inputconsumers.AccessibilityInputConsumer;
@@ -106,8 +103,8 @@ import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
import com.android.systemui.shared.system.RecentsAnimationListener;
import com.android.systemui.shared.system.SystemGestureExclusionListenerCompat;
import com.android.systemui.shared.system.TaskInfoCompat;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.Arrays;
@@ -136,11 +133,14 @@ class ArgList extends LinkedList<String> {
*/
@TargetApi(Build.VERSION_CODES.Q)
public class TouchInteractionService extends Service implements
NavigationModeChangeListener, DisplayListener {
NavigationModeChangeListener, DefaultDisplay.DisplayInfoChangeListener {
/**
* NOTE: This value should be kept same as
* ActivityTaskManagerService#INTENT_EXTRA_LOG_TRACE_ID in platform
*/
public static final String INTENT_EXTRA_LOG_TRACE_ID = "INTENT_EXTRA_LOG_TRACE_ID";
public static final MainThreadExecutor MAIN_THREAD_EXECUTOR = new MainThreadExecutor();
public static final LooperExecutor BACKGROUND_EXECUTOR =
new LooperExecutor(UiThreadHelper.getBackgroundLooper());
public static final EventLogArray TOUCH_INTERACTION_LOG =
new EventLogArray("touch_interaction_log", 40);
@@ -161,9 +161,9 @@ public class TouchInteractionService extends Service implements
public void onInitialize(Bundle bundle) {
mISystemUiProxy = ISystemUiProxy.Stub
.asInterface(bundle.getBinder(KEY_EXTRA_SYSUI_PROXY));
MAIN_THREAD_EXECUTOR.execute(TouchInteractionService.this::initInputMonitor);
MAIN_THREAD_EXECUTOR.execute(TouchInteractionService.this::onSystemUiProxySet);
MAIN_THREAD_EXECUTOR.execute(() -> preloadOverview(true /* fromInit */));
MAIN_EXECUTOR.execute(TouchInteractionService.this::initInputMonitor);
MAIN_EXECUTOR.execute(TouchInteractionService.this::onSystemUiProxySet);
MAIN_EXECUTOR.execute(() -> preloadOverview(true /* fromInit */));
sIsInitialized = true;
}
@@ -198,7 +198,7 @@ public class TouchInteractionService extends Service implements
@Override
public void onAssistantVisibilityChanged(float visibility) {
mLastAssistantVisibility = visibility;
MAIN_THREAD_EXECUTOR.execute(
MAIN_EXECUTOR.execute(
TouchInteractionService.this::onAssistantVisibilityChanged);
}
@@ -214,13 +214,13 @@ public class TouchInteractionService extends Service implements
isButton, gestureSwipeLeft, activityControl.getContainerType());
if (completed && !isButton && shouldNotifyBackGesture()) {
BACKGROUND_EXECUTOR.execute(TouchInteractionService.this::tryNotifyBackGesture);
UI_HELPER_EXECUTOR.execute(TouchInteractionService.this::tryNotifyBackGesture);
}
}
public void onSystemUiStateChanged(int stateFlags) {
mSystemUiStateFlags = stateFlags;
MAIN_THREAD_EXECUTOR.execute(TouchInteractionService.this::onSystemUiFlagsChanged);
MAIN_EXECUTOR.execute(TouchInteractionService.this::onSystemUiFlagsChanged);
}
/** Deprecated methods **/
@@ -244,6 +244,7 @@ public class TouchInteractionService extends Service implements
private static boolean sConnected = false;
private static boolean sIsInitialized = false;
private static final SwipeSharedState sSwipeSharedState = new SwipeSharedState();
private int mLogId;
public static boolean isConnected() {
return sConnected;
@@ -271,7 +272,6 @@ public class TouchInteractionService extends Service implements
private OverviewCommandHelper mOverviewCommandHelper;
private OverviewComponentObserver mOverviewComponentObserver;
private OverviewInteractionState mOverviewInteractionState;
private OverviewCallbacks mOverviewCallbacks;
private TaskOverlayFactory mTaskOverlayFactory;
private InputConsumerController mInputConsumer;
private boolean mAssistantAvailable;
@@ -323,8 +323,7 @@ public class TouchInteractionService extends Service implements
registerReceiver(mUserUnlockedReceiver, new IntentFilter(Intent.ACTION_USER_UNLOCKED));
}
mDefaultDisplayId = getSystemService(WindowManager.class).getDefaultDisplay()
.getDisplayId();
mDefaultDisplayId = DefaultDisplay.INSTANCE.get(this).getInfo().id;
String blockingActivity = getString(R.string.gesture_blocking_activity);
mGestureBlockingActivity = TextUtils.isEmpty(blockingActivity) ? null :
ComponentName.unflattenFromString(blockingActivity);
@@ -391,9 +390,8 @@ public class TouchInteractionService extends Service implements
return;
}
Display defaultDisplay = getSystemService(WindowManager.class).getDefaultDisplay();
Point realSize = new Point();
defaultDisplay.getRealSize(realSize);
DefaultDisplay.Info displayInfo = DefaultDisplay.INSTANCE.get(this).getInfo();
Point realSize = new Point(displayInfo.realSize);
mSwipeTouchRegion.set(0, 0, realSize.x, realSize.y);
if (mMode == Mode.NO_BUTTON) {
int touchHeight = getNavbarSize(ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE);
@@ -415,7 +413,7 @@ public class TouchInteractionService extends Service implements
} else {
mAssistantLeftRegion.setEmpty();
mAssistantRightRegion.setEmpty();
switch (defaultDisplay.getRotation()) {
switch (displayInfo.rotation) {
case Surface.ROTATION_90:
mSwipeTouchRegion.left = mSwipeTouchRegion.right
- getNavbarSize(ResourceUtils.NAVBAR_LANDSCAPE_LEFT_RIGHT_SIZE);
@@ -438,10 +436,9 @@ public class TouchInteractionService extends Service implements
}
if (mMode.hasGestures != newMode.hasGestures) {
if (newMode.hasGestures) {
getSystemService(DisplayManager.class).registerDisplayListener(
this, MAIN_THREAD_EXECUTOR.getHandler());
DefaultDisplay.INSTANCE.get(this).addChangeListener(this);
} else {
getSystemService(DisplayManager.class).unregisterDisplayListener(this);
DefaultDisplay.INSTANCE.get(this).removeChangeListener(this);
}
}
mMode = newMode;
@@ -457,14 +454,8 @@ public class TouchInteractionService extends Service implements
}
@Override
public void onDisplayAdded(int i) { }
@Override
public void onDisplayRemoved(int i) { }
@Override
public void onDisplayChanged(int displayId) {
if (displayId != mDefaultDisplayId) {
public void onDisplayInfoChanged(DefaultDisplay.Info info, int flags) {
if (info.id != mDefaultDisplayId) {
return;
}
@@ -477,7 +468,6 @@ public class TouchInteractionService extends Service implements
mOverviewCommandHelper = new OverviewCommandHelper(this, mOverviewComponentObserver);
mOverviewInteractionState = OverviewInteractionState.INSTANCE.get(this);
mOverviewCallbacks = OverviewCallbacks.get(this);
mTaskOverlayFactory = TaskOverlayFactory.INSTANCE.get(this);
mInputConsumer = InputConsumerController.getRecentsAnimationInputConsumer();
mIsUserUnlocked = true;
@@ -529,7 +519,7 @@ public class TouchInteractionService extends Service implements
}
disposeEventHandlers();
if (mMode.hasGestures) {
getSystemService(DisplayManager.class).unregisterDisplayListener(this);
DefaultDisplay.INSTANCE.get(this).removeChangeListener(this);
}
sConnected = false;
@@ -547,6 +537,7 @@ public class TouchInteractionService extends Service implements
}
private void onInputEvent(InputEvent ev) {
DejankBinderTracker.allowBinderTrackingInTests();
if (TestProtocol.sDebugTracing) {
Log.d(TestProtocol.NO_BACKGROUND_TO_OVERVIEW_TAG, "onInputEvent " + ev);
}
@@ -554,9 +545,12 @@ public class TouchInteractionService extends Service implements
Log.e(TAG, "Unknown event " + ev);
return;
}
MotionEvent event = (MotionEvent) ev;
TOUCH_INTERACTION_LOG.addLog("onMotionEvent", event.getActionMasked());
if (event.getAction() == ACTION_DOWN) {
mLogId = TOUCH_INTERACTION_LOG.generateAndSetLogId();
sSwipeSharedState.setLogTraceId(mLogId);
if (mSwipeTouchRegion.contains(event.getX(), event.getY())) {
boolean useSharedState = mConsumer.useSharedSwipeState();
mConsumer.onConsumerAboutToBeSwitched();
@@ -576,7 +570,10 @@ public class TouchInteractionService extends Service implements
mUncheckedConsumer = InputConsumer.NO_OP;
}
}
TOUCH_INTERACTION_LOG.addLog("onMotionEvent", event.getActionMasked());
mUncheckedConsumer.onMotionEvent(event);
DejankBinderTracker.disallowBinderTrackingInTests();
}
private boolean validSystemUiFlags() {
@@ -640,7 +637,8 @@ public class TouchInteractionService extends Service implements
}
private InputConsumer newBaseConsumer(boolean useSharedState, MotionEvent event) {
RunningTaskInfo runningTaskInfo = mAM.getRunningTask(0);
RunningTaskInfo runningTaskInfo = DejankBinderTracker.whitelistIpcs(
() -> mAM.getRunningTask(0));
if (!useSharedState) {
sSwipeSharedState.clearAllState(false /* finishAnimation */);
}
@@ -656,12 +654,13 @@ public class TouchInteractionService extends Service implements
if (isExcludedAssistant(runningTaskInfo)) {
// In the case where we are in the excluded assistant state, ignore it and treat the
// running activity as the task behind the assistant
runningTaskInfo = mAM.getRunningTask(ACTIVITY_TYPE_ASSISTANT);
runningTaskInfo = DejankBinderTracker.whitelistIpcs(
() -> mAM.getRunningTask(ACTIVITY_TYPE_ASSISTANT));
if (!ActivityManagerWrapper.isHomeTask(runningTaskInfo)) {
final ComponentName homeComponent =
mOverviewComponentObserver.getHomeIntent().getComponent();
forceOverviewInputConsumer =
runningTaskInfo.baseIntent.getComponent().equals(homeComponent);
runningTaskInfo.baseIntent.getComponent(). equals(homeComponent);
}
}
@@ -705,26 +704,26 @@ public class TouchInteractionService extends Service implements
final boolean shouldDefer;
final BaseSwipeUpHandler.Factory factory;
ActivityControlHelper activityControlHelper =
mOverviewComponentObserver.getActivityControlHelper();
if (mMode == Mode.NO_BUTTON && !mOverviewComponentObserver.isHomeAndOverviewSame()) {
shouldDefer = !sSwipeSharedState.recentsAnimationFinishInterrupted;
factory = mFallbackNoButtonFactory;
} else {
shouldDefer = mOverviewComponentObserver.getActivityControlHelper()
.deferStartingActivity(mActiveNavBarRegion, event);
shouldDefer = activityControlHelper.deferStartingActivity(mActiveNavBarRegion, event);
factory = mWindowTreansformFactory;
}
return new OtherActivityInputConsumer(this, runningTaskInfo,
shouldDefer, mOverviewCallbacks, this::onConsumerInactive,
sSwipeSharedState, mInputMonitorCompat, mSwipeTouchRegion,
disableHorizontalSwipe(event), factory);
return new OtherActivityInputConsumer(this, runningTaskInfo, shouldDefer,
this::onConsumerInactive, sSwipeSharedState, mInputMonitorCompat, mSwipeTouchRegion,
disableHorizontalSwipe(event), activityControlHelper, factory, mLogId);
}
private InputConsumer createDeviceLockedInputConsumer(RunningTaskInfo taskInfo) {
if (mMode == Mode.NO_BUTTON && taskInfo != null) {
return new DeviceLockedInputConsumer(this, sSwipeSharedState, mInputMonitorCompat,
mSwipeTouchRegion, taskInfo.taskId);
mSwipeTouchRegion, taskInfo.taskId, mLogId);
} else {
return mResetGestureInputConsumer;
}
@@ -740,10 +739,10 @@ public class TouchInteractionService extends Service implements
if (activity.getRootView().hasWindowFocus() || sSwipeSharedState.goingToLauncher) {
return new OverviewInputConsumer(activity, mInputMonitorCompat,
false /* startingInActivityBounds */);
false /* startingInActivityBounds */, activityControl);
} else {
return new OverviewWithoutFocusInputConsumer(activity, mInputMonitorCompat,
disableHorizontalSwipe(event));
activityControl, disableHorizontalSwipe(event));
}
}
@@ -788,7 +787,8 @@ public class TouchInteractionService extends Service implements
}
// Pass null animation handler to indicate this start is preload.
startRecentsActivityAsync(mOverviewComponentObserver.getOverviewIntentIgnoreSysUiState(), null);
startRecentsActivityAsync(mOverviewComponentObserver.getOverviewIntentIgnoreSysUiState(),
null);
}
@Override
@@ -897,7 +897,7 @@ public class TouchInteractionService extends Service implements
}
public static void startRecentsActivityAsync(Intent intent, RecentsAnimationListener listener) {
BACKGROUND_EXECUTOR.execute(() -> ActivityManagerWrapper.getInstance()
UI_HELPER_EXECUTOR.execute(() -> ActivityManagerWrapper.getInstance()
.startRecentsActivity(intent, null, listener, null, null));
}
}
@@ -68,6 +68,7 @@ import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.logging.UserEventDispatcher;
import com.android.launcher3.uioverrides.DejankBinderTracker;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
@@ -423,9 +424,13 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
private void initializeLauncherAnimationController() {
buildAnimationController();
if (LatencyTrackerCompat.isEnabled(mContext)) {
LatencyTrackerCompat.logToggleRecents((int) (mLauncherFrameDrawnTime - mTouchTimeMs));
}
DejankBinderTracker.whitelistIpcs(() -> {
// Only used in debug builds
if (LatencyTrackerCompat.isEnabled(mContext)) {
LatencyTrackerCompat.logToggleRecents(
(int) (mLauncherFrameDrawnTime - mTouchTimeMs));
}
});
// This method is only called when STATE_GESTURE_STARTED is set, so we can enable the
// high-res thumbnail loader here once we are sure that we will end up in an overview state
@@ -479,8 +484,8 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
recentsAttachedToAppWindow = mIsShelfPeeking || mIsLikelyToStartNewTask;
if (animate) {
// Only animate if an adjacent task view is visible on screen.
TaskView adjacentTask1 = mRecentsView.getTaskViewAt(runningTaskIndex + 1);
TaskView adjacentTask2 = mRecentsView.getTaskViewAt(runningTaskIndex - 1);
TaskView adjacentTask1 = mRecentsView.getNextTaskView();
TaskView adjacentTask2 = mRecentsView.getPreviousTaskView();
float prevTranslationX = mRecentsView.getTranslationX();
mRecentsView.setTranslationX(0);
animate = (adjacentTask1 != null && adjacentTask1.getGlobalVisibleRect(TEMP_RECT))
@@ -590,8 +595,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
*/
private void updateSysUiFlags(float windowProgress) {
if (mRecentsView != null) {
TaskView centermostTask = mRecentsView.getTaskViewAt(mRecentsView
.getPageNearestToCenterOfScreen());
TaskView centermostTask = mRecentsView.getTaskViewNearestToCenterOfScreen();
int centermostTaskFlags = centermostTask == null ? 0
: centermostTask.getThumbnail().getSysUiStatusNavFlags();
boolean useHomeScreenFlags = windowProgress > 1 - UPDATE_SYSUI_FLAGS_THRESHOLD;
@@ -685,8 +689,8 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
}
BaseDraggingActivity activity = mActivityControlHelper.getCreatedActivity();
return activity == null
? InputConsumer.NO_OP : new OverviewInputConsumer(activity, null, true);
return activity == null ? InputConsumer.NO_OP
: new OverviewInputConsumer(activity, null, true, mActivityControlHelper);
}
private void endRunningWindowAnim(boolean cancel) {
@@ -176,7 +176,7 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity> {
protected void applyLoadPlan(ArrayList<Task> tasks) {
// When quick-switching on 3p-launcher, we add a "dummy" tile corresponding to Launcher
// as well. This tile is never shown as we have setCurrentTaskHidden, but allows use to
// track the index of the next task appropriately, as it we are switching on any other app.
// track the index of the next task appropriately, as if we are switching on any other app.
if (mRunningTaskInfo != null && mRunningTaskInfo.taskId == mRunningTaskId) {
// Check if the task list has running task
boolean found = false;
@@ -22,8 +22,9 @@ import static android.view.MotionEvent.ACTION_UP;
import static com.android.launcher3.Utilities.squaredHypot;
import static com.android.launcher3.Utilities.squaredTouchSlop;
import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
import static com.android.quickstep.WindowTransformSwipeHandler.MIN_PROGRESS_FOR_OVERVIEW;
import static com.android.quickstep.TouchInteractionService.INTENT_EXTRA_LOG_TRACE_ID;
import static com.android.quickstep.TouchInteractionService.startRecentsActivityAsync;
import static com.android.quickstep.WindowTransformSwipeHandler.MIN_PROGRESS_FOR_OVERVIEW;
import android.content.ComponentName;
import android.content.Context;
@@ -35,10 +36,10 @@ import android.graphics.RectF;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.ViewConfiguration;
import android.view.WindowManager;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.util.DefaultDisplay;
import com.android.quickstep.LockScreenRecentsActivity;
import com.android.quickstep.MultiStateCallback;
import com.android.quickstep.SwipeSharedState;
@@ -76,6 +77,7 @@ public class DeviceLockedInputConsumer implements InputConsumer,
private final PointF mTouchDown = new PointF();
private final ClipAnimationHelper mClipAnimationHelper;
private int mLogId;
private final ClipAnimationHelper.TransformParams mTransformParams;
private final Point mDisplaySize;
private final MultiStateCallback mStateCallback;
@@ -90,19 +92,20 @@ public class DeviceLockedInputConsumer implements InputConsumer,
private SwipeAnimationTargetSet mTargetSet;
public DeviceLockedInputConsumer(Context context, SwipeSharedState swipeSharedState,
InputMonitorCompat inputMonitorCompat, RectF swipeTouchRegion, int runningTaskId) {
InputMonitorCompat inputMonitorCompat, RectF swipeTouchRegion, int runningTaskId,
int logId) {
mContext = context;
mTouchSlopSquared = squaredTouchSlop(context);
mSwipeSharedState = swipeSharedState;
mClipAnimationHelper = new ClipAnimationHelper(context);
mLogId = logId;
mTransformParams = new ClipAnimationHelper.TransformParams();
mInputMonitorCompat = inputMonitorCompat;
mSwipeTouchRegion = swipeTouchRegion;
mRunningTaskId = runningTaskId;
// Do not use DeviceProfile as the user data might be locked
mDisplaySize = new Point();
context.getSystemService(WindowManager.class).getDefaultDisplay().getRealSize(mDisplaySize);
mDisplaySize = DefaultDisplay.INSTANCE.get(context).getInfo().realSize;
// Init states
mStateCallback = new MultiStateCallback(STATE_NAMES);
@@ -205,7 +208,8 @@ public class DeviceLockedInputConsumer implements InputConsumer,
Intent intent = new Intent(Intent.ACTION_MAIN)
.addCategory(Intent.CATEGORY_DEFAULT)
.setComponent(new ComponentName(mContext, LockScreenRecentsActivity.class))
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK)
.putExtra(INTENT_EXTRA_LOG_TRACE_ID, mLogId);
mInputMonitorCompat.pilferPointers();
startRecentsActivityAsync(intent, newListenerSet);
@@ -50,7 +50,6 @@ import com.android.quickstep.fallback.FallbackRecentsView;
import com.android.quickstep.util.ObjectWrapper;
import com.android.quickstep.util.RectFSpringAnim;
import com.android.quickstep.util.SwipeAnimationTargetSet;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -27,6 +27,7 @@ import static com.android.launcher3.Utilities.EDGE_NAV_BAR;
import static com.android.launcher3.Utilities.squaredHypot;
import static com.android.launcher3.util.RaceConditionTracker.ENTER;
import static com.android.launcher3.util.RaceConditionTracker.EXIT;
import static com.android.quickstep.TouchInteractionService.INTENT_EXTRA_LOG_TRACE_ID;
import static com.android.quickstep.TouchInteractionService.TOUCH_INTERACTION_LOG;
import static com.android.quickstep.TouchInteractionService.startRecentsActivityAsync;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
@@ -35,6 +36,7 @@ import android.annotation.TargetApi;
import android.app.ActivityManager.RunningTaskInfo;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.graphics.PointF;
import android.graphics.RectF;
import android.os.Build;
@@ -44,12 +46,15 @@ import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.ViewConfiguration;
import androidx.annotation.UiThread;
import com.android.launcher3.R;
import com.android.launcher3.util.Preconditions;
import com.android.launcher3.util.RaceConditionTracker;
import com.android.launcher3.util.TraceHelper;
import com.android.quickstep.ActivityControlHelper;
import com.android.quickstep.BaseSwipeUpHandler;
import com.android.quickstep.OverviewCallbacks;
import com.android.quickstep.BaseSwipeUpHandler.Factory;
import com.android.quickstep.SwipeSharedState;
import com.android.quickstep.SysUINavigationMode;
import com.android.quickstep.SysUINavigationMode.Mode;
@@ -62,8 +67,6 @@ import com.android.systemui.shared.system.InputMonitorCompat;
import java.util.function.Consumer;
import androidx.annotation.UiThread;
/**
* Input consumer for handling events originating from an activity other than Launcher
*/
@@ -78,11 +81,11 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
private final CachedEventDispatcher mRecentsViewDispatcher = new CachedEventDispatcher();
private final RunningTaskInfo mRunningTask;
private final OverviewCallbacks mOverviewCallbacks;
private final SwipeSharedState mSwipeSharedState;
private final InputMonitorCompat mInputMonitorCompat;
private final SysUINavigationMode.Mode mMode;
private final RectF mSwipeTouchRegion;
private final ActivityControlHelper mActivityControlHelper;
private final BaseSwipeUpHandler.Factory mHandlerFactory;
@@ -119,20 +122,23 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
ActivityManagerWrapper.getInstance().cancelRecentsAnimation(
true /* restoreHomeStackPosition */);
};
private int mLogId;
public OtherActivityInputConsumer(Context base, RunningTaskInfo runningTaskInfo,
boolean isDeferredDownTarget, OverviewCallbacks overviewCallbacks,
Consumer<OtherActivityInputConsumer> onCompleteCallback,
boolean isDeferredDownTarget, Consumer<OtherActivityInputConsumer> onCompleteCallback,
SwipeSharedState swipeSharedState, InputMonitorCompat inputMonitorCompat,
RectF swipeTouchRegion, boolean disableHorizontalSwipe,
BaseSwipeUpHandler.Factory handlerFactory) {
ActivityControlHelper activityControlHelper,
Factory handlerFactory, int logId) {
super(base);
mLogId = logId;
mMainThreadHandler = new Handler(Looper.getMainLooper());
mRunningTask = runningTaskInfo;
mMode = SysUINavigationMode.getMode(base);
mSwipeTouchRegion = swipeTouchRegion;
mHandlerFactory = handlerFactory;
mActivityControlHelper = activityControlHelper;
mMotionPauseDetector = new MotionPauseDetector(base);
mMotionPauseMinDisplacement = base.getResources().getDimension(
@@ -143,7 +149,6 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
boolean continuingPreviousGesture = swipeSharedState.getActiveListener() != null;
mIsDeferredDownTarget = !continuingPreviousGesture && isDeferredDownTarget;
mOverviewCallbacks = overviewCallbacks;
mSwipeSharedState = swipeSharedState;
mNavBarPosition = new NavBarPosition(base);
@@ -312,7 +317,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
}
mInputMonitorCompat.pilferPointers();
mOverviewCallbacks.closeAllWindows();
mActivityControlHelper.closeOverlay();
ActivityManagerWrapper.getInstance().closeSystemWindows(
CLOSE_SYSTEM_WINDOWS_REASON_RECENTS);
@@ -341,7 +346,9 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
RecentsAnimationListenerSet newListenerSet =
mSwipeSharedState.newRecentsAnimationListenerSet();
newListenerSet.addListener(handler);
startRecentsActivityAsync(handler.getLaunchIntent(), newListenerSet);
Intent intent = handler.getLaunchIntent();
intent.putExtra(INTENT_EXTRA_LOG_TRACE_ID, mLogId);
startRecentsActivityAsync(intent, newListenerSet);
}
}
@@ -19,7 +19,6 @@ import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TI
import static com.android.quickstep.TouchInteractionService.TOUCH_INTERACTION_LOG;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
@@ -27,9 +26,8 @@ import androidx.annotation.Nullable;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.Utilities;
import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.views.BaseDragLayer;
import com.android.quickstep.OverviewCallbacks;
import com.android.quickstep.ActivityControlHelper;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.InputMonitorCompat;
@@ -42,6 +40,7 @@ public class OverviewInputConsumer<T extends BaseDraggingActivity>
implements InputConsumer {
private final T mActivity;
private final ActivityControlHelper<T> mActivityControlHelper;
private final BaseDragLayer mTarget;
private final InputMonitorCompat mInputMonitor;
@@ -53,10 +52,12 @@ public class OverviewInputConsumer<T extends BaseDraggingActivity>
private boolean mTargetHandledTouch;
public OverviewInputConsumer(T activity, @Nullable InputMonitorCompat inputMonitor,
boolean startingInActivityBounds) {
boolean startingInActivityBounds,
ActivityControlHelper<T> activityControlHelper) {
mActivity = activity;
mInputMonitor = inputMonitor;
mStartingInActivityBounds = startingInActivityBounds;
mActivityControlHelper = activityControlHelper;
mTarget = activity.getDragLayer();
if (startingInActivityBounds) {
@@ -98,7 +99,7 @@ public class OverviewInputConsumer<T extends BaseDraggingActivity>
if (!mTargetHandledTouch && handled) {
mTargetHandledTouch = true;
if (!mStartingInActivityBounds) {
OverviewCallbacks.get(mActivity).closeAllWindows();
mActivityControlHelper.closeOverlay();
ActivityManagerWrapper.getInstance()
.closeSystemWindows(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS);
TOUCH_INTERACTION_LOG.addLog("startQuickstep");
@@ -34,10 +34,9 @@ import com.android.launcher3.BaseActivity;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.Utilities;
import com.android.launcher3.logging.StatsLogUtils;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
import com.android.quickstep.OverviewCallbacks;
import com.android.quickstep.ActivityControlHelper;
import com.android.quickstep.util.NavBarPosition;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.InputMonitorCompat;
@@ -50,16 +49,17 @@ public class OverviewWithoutFocusInputConsumer implements InputConsumer {
private final float mSquaredTouchSlop;
private final Context mContext;
private final NavBarPosition mNavBarPosition;
private final ActivityControlHelper mActivityControlHelper;
private boolean mInterceptedTouch;
private VelocityTracker mVelocityTracker;
public OverviewWithoutFocusInputConsumer(Context context, InputMonitorCompat inputMonitor,
boolean disableHorizontalSwipe) {
ActivityControlHelper activityControlHelper, boolean disableHorizontalSwipe) {
mInputMonitor = inputMonitor;
mDisableHorizontalSwipe = disableHorizontalSwipe;
mContext = context;
mActivityControlHelper = activityControlHelper;
mSquaredTouchSlop = Utilities.squaredTouchSlop(context);
mNavBarPosition = new NavBarPosition(context);
@@ -148,7 +148,7 @@ public class OverviewWithoutFocusInputConsumer implements InputConsumer {
}
if (triggerQuickstep) {
OverviewCallbacks.get(mContext).closeAllWindows();
mActivityControlHelper.closeOverlay();
ActivityManagerWrapper.getInstance()
.closeSystemWindows(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS);
TOUCH_INTERACTION_LOG.addLog("startQuickstep");
@@ -21,9 +21,9 @@ import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
import android.content.Context;
import android.view.Surface;
import android.view.WindowManager;
import com.android.launcher3.graphics.RotationMode;
import com.android.launcher3.util.DefaultDisplay;
import com.android.quickstep.SysUINavigationMode;
/**
@@ -36,8 +36,7 @@ public class NavBarPosition {
public NavBarPosition(Context context) {
mMode = SysUINavigationMode.getMode(context);
mDisplayRotation = context.getSystemService(WindowManager.class)
.getDefaultDisplay().getRotation();
mDisplayRotation = DefaultDisplay.INSTANCE.get(context).getInfo().rotation;
}
public boolean isRightEdge() {
@@ -15,11 +15,14 @@
*/
package com.android.quickstep.util;
import static com.android.quickstep.TouchInteractionService.MAIN_THREAD_EXECUTOR;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import android.graphics.Rect;
import android.util.ArraySet;
import androidx.annotation.BinderThread;
import androidx.annotation.UiThread;
import com.android.launcher3.Utilities;
import com.android.launcher3.util.Preconditions;
import com.android.quickstep.util.SwipeAnimationTargetSet.SwipeAnimationListener;
@@ -31,8 +34,6 @@ import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import java.util.Set;
import java.util.function.Consumer;
import androidx.annotation.UiThread;
/**
* Wrapper around {@link RecentsAnimationListener} which delegates callbacks to multiple listeners
* on the main thread
@@ -70,19 +71,21 @@ public class RecentsAnimationListenerSet implements RecentsAnimationListener {
mListeners.remove(listener);
}
@Override
// Called only in R+ platform
@BinderThread
public final void onAnimationStart(RecentsAnimationControllerCompat controller,
RemoteAnimationTargetCompat[] targets, Rect homeContentInsets,
Rect minimizedHomeBounds) {
RemoteAnimationTargetCompat[] appTargets,
RemoteAnimationTargetCompat[] wallpaperTargets,
Rect homeContentInsets, Rect minimizedHomeBounds) {
mController = controller;
SwipeAnimationTargetSet targetSet = new SwipeAnimationTargetSet(controller, targets,
SwipeAnimationTargetSet targetSet = new SwipeAnimationTargetSet(controller, appTargets,
homeContentInsets, minimizedHomeBounds, mShouldMinimizeSplitScreen,
mOnFinishListener);
if (mCancelled) {
targetSet.cancelAnimation();
} else {
Utilities.postAsyncCallback(MAIN_THREAD_EXECUTOR.getHandler(), () -> {
Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(), () -> {
for (SwipeAnimationListener listener : getListeners()) {
listener.onRecentsAnimationStart(targetSet);
}
@@ -90,16 +93,27 @@ public class RecentsAnimationListenerSet implements RecentsAnimationListener {
}
}
// Called only in Q platform
@BinderThread
@Deprecated
public final void onAnimationStart(RecentsAnimationControllerCompat controller,
RemoteAnimationTargetCompat[] appTargets, Rect homeContentInsets,
Rect minimizedHomeBounds) {
onAnimationStart(controller, appTargets, new RemoteAnimationTargetCompat[0],
homeContentInsets, minimizedHomeBounds);
}
@BinderThread
@Override
public final void onAnimationCanceled(ThumbnailData thumbnailData) {
Utilities.postAsyncCallback(MAIN_THREAD_EXECUTOR.getHandler(), () -> {
Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(), () -> {
for (SwipeAnimationListener listener : getListeners()) {
listener.onRecentsAnimationCanceled();
}
});
// TODO: handle the transition better instead of simply using a transition delay.
if (thumbnailData != null) {
MAIN_THREAD_EXECUTOR.getHandler().postDelayed(() -> mController.cleanupScreenshot(),
MAIN_EXECUTOR.getHandler().postDelayed(() -> mController.cleanupScreenshot(),
TRANSITION_DELAY);
}
}
@@ -15,8 +15,8 @@
*/
package com.android.quickstep.util;
import static com.android.quickstep.TouchInteractionService.BACKGROUND_EXECUTOR;
import static com.android.quickstep.TouchInteractionService.MAIN_THREAD_EXECUTOR;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
import android.graphics.Rect;
@@ -68,25 +68,25 @@ public class SwipeAnimationTargetSet extends RemoteAnimationTargetSet {
public void finishController(boolean toRecents, Runnable callback, boolean sendUserLeaveHint) {
mOnFinishListener.accept(this);
BACKGROUND_EXECUTOR.execute(() -> {
UI_HELPER_EXECUTOR.execute(() -> {
controller.setInputConsumerEnabled(false);
controller.finish(toRecents, sendUserLeaveHint);
if (callback != null) {
MAIN_THREAD_EXECUTOR.execute(callback);
MAIN_EXECUTOR.execute(callback);
}
});
}
public void enableInputConsumer() {
BACKGROUND_EXECUTOR.submit(() -> {
UI_HELPER_EXECUTOR.submit(() -> {
controller.hideCurrentInputMethod();
controller.setInputConsumerEnabled(true);
});
}
public void setWindowThresholdCrossed(boolean thresholdCrossed) {
BACKGROUND_EXECUTOR.execute(() -> {
UI_HELPER_EXECUTOR.execute(() -> {
controller.setAnimationTargetsBehindSystemBars(!thresholdCrossed);
if (mShouldMinimizeSplitScreen && thresholdCrossed) {
// NOTE: As a workaround for conflicting animations (Launcher animating the task
@@ -19,6 +19,7 @@ package com.android.quickstep.views;
import static android.provider.Settings.ACTION_APP_USAGE_SETTINGS;
import static com.android.launcher3.Utilities.prefixTextWithIcon;
import static com.android.launcher3.util.Executors.THREAD_POOL_EXECUTOR;
import android.annotation.TargetApi;
import android.app.ActivityOptions;
@@ -41,7 +42,6 @@ import androidx.annotation.StringRes;
import com.android.launcher3.BaseActivity;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.systemui.shared.recents.model.Task;
@@ -117,7 +117,7 @@ public final class DigitalWellBeingToast {
return;
}
Utilities.THREAD_POOL_EXECUTOR.execute(() -> {
THREAD_POOL_EXECUTOR.execute(() -> {
final AppUsageLimit usageLimit = mLauncherApps.getAppUsageLimit(
task.getTopComponent().getPackageName(),
UserHandle.of(task.key.userId));
@@ -45,6 +45,7 @@ import com.android.launcher3.R;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.appprediction.PredictionUiStateManager;
import com.android.launcher3.appprediction.PredictionUiStateManager.Client;
import com.android.launcher3.uioverrides.DejankBinderTracker;
import com.android.launcher3.views.ScrimView;
import com.android.quickstep.SysUINavigationMode;
import com.android.quickstep.util.ClipAnimationHelper;
@@ -172,7 +173,7 @@ public class LauncherRecentsView extends RecentsView<Launcher> implements StateL
@Override
public boolean shouldUseMultiWindowTaskSizeStrategy() {
return mActivity.isInMultiWindowMode();
return DejankBinderTracker.whitelistIpcs(() -> mActivity.isInMultiWindowMode());
}
@Override
@@ -35,9 +35,9 @@ import static com.android.launcher3.config.FeatureFlags.QUICKSTEP_SPRINGS;
import static com.android.launcher3.uioverrides.touchcontrollers.TaskViewTouchController.SUCCESS_TRANSITION_PROGRESS;
import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch.TAP;
import static com.android.launcher3.userevent.nano.LauncherLogProto.ControlType.CLEAR_ALL_BUTTON;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.launcher3.util.SystemUiController.UI_STATE_OVERVIEW;
import static com.android.quickstep.TaskUtils.checkCurrentOrManagedUserId;
import static com.android.quickstep.TouchInteractionService.BACKGROUND_EXECUTOR;
import android.animation.Animator;
import android.animation.AnimatorSet;
@@ -228,7 +228,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
return;
}
BACKGROUND_EXECUTOR.execute(() -> {
UI_HELPER_EXECUTOR.execute(() -> {
TaskView taskView = getTaskView(taskId);
if (taskView == null) {
return;
@@ -306,6 +306,9 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
private Layout mEmptyTextLayout;
private LiveTileOverlay mLiveTileOverlay;
// Keeps track of the index where the first TaskView should be
private int mTaskViewStartIndex = 0;
private BaseActivity.MultiWindowModeChangedListener mMultiWindowModeChangedListener =
(inMultiWindowMode) -> {
if (!inMultiWindowMode && mOverviewStateEnabled) {
@@ -329,7 +332,6 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
mClearAllButton = (ClearAllButton) LayoutInflater.from(context)
.inflate(R.layout.overview_clear_all_button, this, false);
mClearAllButton.setOnClickListener(this::dismissAllTasks);
mTaskViewPool = new ViewPool<>(context, this, R.layout.task, 20 /* max size */,
10 /* initial size */);
@@ -430,7 +432,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
super.onViewRemoved(child);
// Clear the task data for the removed child if it was visible
if (child != mClearAllButton) {
if (child instanceof TaskView) {
TaskView taskView = (TaskView) child;
mHasVisibleTaskData.delete(taskView.getTask().key.id);
mTaskViewPool.recycle(taskView);
@@ -444,7 +446,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
public TaskView getTaskView(int taskId) {
for (int i = 0; i < getTaskViewCount(); i++) {
TaskView tv = (TaskView) getChildAt(i);
TaskView tv = getTaskViewAt(i);
if (tv.getTask() != null && tv.getTask().key != null && tv.getTask().key.id == taskId) {
return tv;
}
@@ -536,28 +538,26 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
}
if (tasks == null || tasks.isEmpty()) {
removeAllViews();
removeTasksViewsAndClearAllButton();
onTaskStackUpdated();
return;
}
int oldChildCount = getChildCount();
// Unload existing visible task data
unloadVisibleTaskData();
TaskView ignoreRestTaskView =
TaskView ignoreResetTaskView =
mIgnoreResetTaskId == -1 ? null : getTaskView(mIgnoreResetTaskId);
final int requiredTaskCount = tasks.size();
if (getTaskViewCount() != requiredTaskCount) {
if (oldChildCount > 0) {
if (indexOfChild(mClearAllButton) != -1) {
removeView(mClearAllButton);
}
for (int i = getChildCount(); i < requiredTaskCount; i++) {
for (int i = getTaskViewCount(); i < requiredTaskCount; i++) {
addView(mTaskViewPool.getView());
}
while (getChildCount() > requiredTaskCount) {
while (getTaskViewCount() > requiredTaskCount) {
removeView(getChildAt(getChildCount() - 1));
}
if (requiredTaskCount > 0) {
@@ -567,17 +567,20 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
// Rebind and reset all task views
for (int i = requiredTaskCount - 1; i >= 0; i--) {
final int pageIndex = requiredTaskCount - i - 1;
final int pageIndex = requiredTaskCount - i - 1 + mTaskViewStartIndex;
final Task task = tasks.get(i);
final TaskView taskView = (TaskView) getChildAt(pageIndex);
taskView.bind(task);
}
TaskView runningTaskView = getRunningTaskView();
if (runningTaskView != null) {
setCurrentPage(indexOfChild(runningTaskView));
} else if (getTaskViewCount() > 0) {
setCurrentPage(indexOfChild(getTaskViewAt(0)));
}
if (mIgnoreResetTaskId != -1 && getTaskView(mIgnoreResetTaskId) != ignoreRestTaskView) {
if (mIgnoreResetTaskId != -1 && getTaskView(mIgnoreResetTaskId) != ignoreResetTaskView) {
// If the taskView mapping is changing, do not preserve the visuals. Since we are
// mostly preserving the first task, and new taskViews are added to the end, it should
// generally map to the same task.
@@ -588,17 +591,28 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
updateEnabledOverlays();
}
private void removeTasksViewsAndClearAllButton() {
for (int i = getTaskViewCount() - 1; i >= 0; i--) {
removeView(getTaskViewAt(i));
}
if (indexOfChild(mClearAllButton) != -1) {
removeView(mClearAllButton);
}
}
public int getTaskViewCount() {
// Account for the clear all button.
int childCount = getChildCount();
return childCount == 0 ? 0 : childCount - 1;
int taskViewCount = getChildCount() - mTaskViewStartIndex;
if (indexOfChild(mClearAllButton) != -1) {
taskViewCount--;
}
return taskViewCount;
}
protected void onTaskStackUpdated() { }
public void resetTaskVisuals() {
for (int i = getTaskViewCount() - 1; i >= 0; i--) {
TaskView taskView = (TaskView) getChildAt(i);
TaskView taskView = getTaskViewAt(i);
if (mIgnoreResetTaskId != taskView.getTask().key.id) {
taskView.resetVisualProperties();
taskView.setStableAlpha(mContentAlpha);
@@ -704,7 +718,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
}
/**
* Iterates through all thet asks, and loads the associated task data for newly visible tasks,
* Iterates through all the tasks, and loads the associated task data for newly visible tasks,
* and unloads the associated task data for tasks that are no longer visible.
*/
public void loadVisibleTaskData() {
@@ -715,15 +729,16 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
}
int centerPageIndex = getPageNearestToCenterOfScreen();
int numChildren = getTaskViewCount();
int numChildren = getChildCount();
int lower = Math.max(0, centerPageIndex - 2);
int upper = Math.min(centerPageIndex + 2, numChildren - 1);
// Update the task data for the in/visible children
for (int i = 0; i < numChildren; i++) {
TaskView taskView = (TaskView) getChildAt(i);
for (int i = 0; i < getTaskViewCount(); i++) {
TaskView taskView = getTaskViewAt(i);
Task task = taskView.getTask();
boolean visible = lower <= i && i <= upper;
int index = indexOfChild(taskView);
boolean visible = lower <= index && index <= upper;
if (visible) {
if (task == mTmpRunningTask) {
// Skip loading if this is the task that we are animating into
@@ -798,6 +813,10 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
return tv == null ? -1 : indexOfChild(tv);
}
public int getTaskViewStartIndex() {
return mTaskViewStartIndex;
}
/**
* Reloads the view if anything in recents changed.
*/
@@ -853,10 +872,10 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
*/
public void showCurrentTask(int runningTaskId) {
if (getTaskView(runningTaskId) == null) {
boolean wasEmpty = getChildCount() == 0;
boolean wasEmpty = getTaskViewCount() == 0;
// Add an empty view for now until the task plan is loaded and applied
final TaskView taskView = mTaskViewPool.getView();
addView(taskView, 0);
addView(taskView, mTaskViewStartIndex);
if (wasEmpty) {
addView(mClearAllButton);
}
@@ -922,14 +941,13 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
if (runningTaskView == null) {
// Launch the first task
if (getTaskViewCount() > 0) {
getTaskViewAt(0).launchTask(true /* animate */);
getTaskViewAt(0).launchTask(true);
}
} else {
TaskView nextTaskView = getNextTaskView();
if (nextTaskView != null) {
nextTaskView.launchTask(true /* animate */);
if (getNextTaskView() != null) {
getNextTaskView().launchTask(true);
} else {
runningTaskView.launchTask(true /* animate */);
runningTaskView.launchTask(true);
}
}
}
@@ -941,6 +959,10 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
}
}
public boolean isTaskIconScaledDown(TaskView taskView) {
return mRunningTaskIconScaledDown && getRunningTaskView() == taskView;
}
private void applyRunningTaskIconScale() {
TaskView firstTask = getRunningTaskView();
if (firstTask != null) {
@@ -1189,7 +1211,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
int count = getTaskViewCount();
for (int i = 0; i < count; i++) {
addDismissedTaskAnimations(getChildAt(i), anim, duration);
addDismissedTaskAnimations(getTaskViewAt(i), anim, duration);
}
mPendingAnimation = pendingAnimation;
@@ -1197,7 +1219,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
if (onEndListener.isSuccess) {
// Remove all the task views now
ActivityManagerWrapper.getInstance().removeAllRecentTasks();
removeAllViews();
removeTasksViewsAndClearAllButton();
startHome();
}
mPendingAnimation = null;
@@ -1344,26 +1366,50 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
child.setAlpha(mContentAlpha);
}
/**
* @return The most recent task that is older than the currently running task. If there is
* currently no running task or there is no task older than it, then return null.
*/
@Nullable
public TaskView getNextTaskView() {
TaskView runningTaskView = getRunningTaskView();
if (runningTaskView == null) {
return null;
}
return getTaskViewAt(indexOfChild(runningTaskView) + 1);
return getTaskViewAtByAbsoluteIndex(getRunningTaskIndex() + 1);
}
@Nullable
public TaskView getPreviousTaskView() {
return getTaskViewAtByAbsoluteIndex(getRunningTaskIndex() - 1);
}
@Nullable
public TaskView getCurrentPageTaskView() {
return getTaskViewAtByAbsoluteIndex(getCurrentPage());
}
@Nullable
public TaskView getNextPageTaskView() {
return getTaskViewAtByAbsoluteIndex(getNextPage());
}
@Nullable
public TaskView getTaskViewNearestToCenterOfScreen() {
return getTaskViewAtByAbsoluteIndex(getPageNearestToCenterOfScreen());
}
/**
* Returns null instead of indexOutOfBoundsError when index is not in range
*/
@Nullable
public TaskView getTaskViewAt(int index) {
View child = getChildAt(index);
return child == mClearAllButton ? null : (TaskView) child;
return getTaskViewAtByAbsoluteIndex(index + mTaskViewStartIndex);
}
@Nullable
private TaskView getTaskViewAtByAbsoluteIndex(int index) {
if (index < getChildCount() && index >= 0) {
View child = getChildAt(index);
return child instanceof TaskView ? (TaskView) child : null;
}
return null;
}
public void updateEmptyMessage() {
boolean isEmpty = getChildCount() == 0;
boolean isEmpty = getTaskViewCount() == 0;
boolean hasSizeChanged = mLastMeasureSize.x != getWidth()
|| mLastMeasureSize.y != getHeight();
if (isEmpty == mShowEmptyMessage && !hasSizeChanged) {
@@ -1497,7 +1543,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
throw new IllegalStateException("Another pending animation is still running");
}
int count = getChildCount();
int count = getTaskViewCount();
if (count == 0) {
return new PendingAnimation(new AnimatorSet());
}
@@ -1670,18 +1716,38 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
@Override
protected int computeMinScrollX() {
if (mIsRtl && mDisallowScrollToClearAll) {
// We aren't showing the clear all button, so use the leftmost task as the min scroll.
return getScrollForPage(getTaskViewCount() - 1);
if (getTaskViewCount() > 0) {
if (mDisallowScrollToClearAll) {
// We aren't showing the clear all button,
// so use the leftmost task as the min scroll.
if (mIsRtl) {
return getScrollForPage(indexOfChild(getTaskViewAt(getTaskViewCount() - 1)));
}
return getScrollForPage(mTaskViewStartIndex);
}
if (mIsRtl) {
return getScrollForPage(indexOfChild(getTaskViewAt(getTaskViewCount() - 1)) + 1);
}
return getScrollForPage(mTaskViewStartIndex);
}
return super.computeMinScrollX();
}
@Override
protected int computeMaxScrollX() {
if (!mIsRtl && mDisallowScrollToClearAll) {
// We aren't showing the clear all button, so use the rightmost task as the max scroll.
return getScrollForPage(getTaskViewCount() - 1);
if (getTaskViewCount() > 0) {
if (mDisallowScrollToClearAll) {
// We aren't showing the clear all button,
// so use the rightmost task as the min scroll.
if (mIsRtl) {
return getScrollForPage(mTaskViewStartIndex);
}
return getScrollForPage(indexOfChild(getTaskViewAt(getTaskViewCount() - 1)));
}
if (mIsRtl) {
return getScrollForPage(mTaskViewStartIndex);
}
return getScrollForPage(indexOfChild(getTaskViewAt(getTaskViewCount() - 1)) + 1);
}
return super.computeMaxScrollX();
}
@@ -1733,7 +1799,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
int overlayEnabledPage = mOverlayEnabled ? getNextPage() : -1;
int taskCount = getTaskViewCount();
for (int i = 0; i < taskCount; i++) {
((TaskView) getChildAt(i)).setOverlayEnabled(i == overlayEnabledPage);
getTaskViewAt(i).setOverlayEnabled(i == overlayEnabledPage);
}
}
@@ -44,7 +44,6 @@ import com.android.launcher3.BaseActivity;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.util.SystemUiController;
import com.android.launcher3.util.Themes;
import com.android.quickstep.TaskOverlayFactory;
@@ -308,8 +307,7 @@ public class TaskThumbnailView extends View {
final Configuration configuration =
getContext().getResources().getConfiguration();
// Rotate the screenshot if not in multi-window mode
isRotated = FeatureFlags.OVERVIEW_USE_SCREENSHOT_ORIENTATION &&
configuration.orientation != mThumbnailData.orientation &&
isRotated = configuration.orientation != mThumbnailData.orientation &&
!mActivity.isInMultiWindowMode() &&
mThumbnailData.windowingMode == WINDOWING_MODE_FULLSCREEN;
// Scale the screenshot to always fit the width of the card.
@@ -28,7 +28,6 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.app.ActivityOptions;
import android.content.Context;
import android.content.res.Resources;
@@ -54,7 +53,6 @@ import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.logging.UserEventDispatcher;
import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
@@ -818,8 +816,11 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
/ (getWidth() + currentInsetsLeft + currentInsetsRight));
}
// Some of the items in here are dependent on the current fullscreen params
setIconScaleAndDim(progress, true /* invert */);
if (!getRecentsView().isTaskIconScaledDown(this)) {
// Some of the items in here are dependent on the current fullscreen params, but don't
// update them if the icon is supposed to be scaled down.
setIconScaleAndDim(progress, true /* invert */);
}
thumbnail.setFullscreenParams(mCurrentFullscreenParams);
mOutlineProvider.setFullscreenParams(mCurrentFullscreenParams);
-2
View File
@@ -16,8 +16,6 @@
<resources>
<string name="task_overlay_factory_class" translatable="false"></string>
<string name="overview_callbacks_class" translatable="false"></string>
<!-- Activity which blocks home gesture -->
<string name="gesture_blocking_activity" translatable="false"></string>
@@ -28,12 +28,12 @@ import android.content.Context;
import android.os.Build;
import android.os.Handler;
import com.android.systemui.shared.system.RemoteAnimationRunnerCompat;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import androidx.annotation.BinderThread;
import androidx.annotation.UiThread;
import com.android.systemui.shared.system.RemoteAnimationRunnerCompat;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
@TargetApi(Build.VERSION_CODES.P)
public abstract class LauncherAnimationRunner implements RemoteAnimationRunnerCompat {
@@ -50,13 +50,14 @@ public abstract class LauncherAnimationRunner implements RemoteAnimationRunnerCo
mStartAtFrontOfQueue = startAtFrontOfQueue;
}
// Called only in R+ platform
@BinderThread
@Override
public void onAnimationStart(RemoteAnimationTargetCompat[] targetCompats, Runnable runnable) {
public void onAnimationStart(RemoteAnimationTargetCompat[] appTargets,
RemoteAnimationTargetCompat[] wallpaperTargets, Runnable runnable) {
Runnable r = () -> {
finishExistingAnimation();
mAnimationResult = new AnimationResult(runnable);
onCreateAnimation(targetCompats, mAnimationResult);
onCreateAnimation(appTargets, mAnimationResult);
};
if (mStartAtFrontOfQueue) {
postAtFrontOfQueueAsynchronously(mHandler, r);
@@ -65,6 +66,13 @@ public abstract class LauncherAnimationRunner implements RemoteAnimationRunnerCo
}
}
// Called only in Q platform
@BinderThread
@Deprecated
public void onAnimationStart(RemoteAnimationTargetCompat[] appTargets, Runnable runnable) {
onAnimationStart(appTargets, new RemoteAnimationTargetCompat[0], runnable);
}
/**
* Called on the UI thread when the animation targets are received. The implementation must
* call {@link AnimationResult#setAnimation} with the target animation to be run.
@@ -25,7 +25,6 @@ import android.os.Handler;
import com.android.launcher3.states.InternalStateHandler;
import com.android.quickstep.ActivityControlHelper.ActivityInitListener;
import com.android.quickstep.OverviewCallbacks;
import com.android.quickstep.util.RemoteAnimationProvider;
import java.util.function.BiPredicate;
@@ -63,7 +62,7 @@ public class LauncherInitListener extends InternalStateHandler implements Activi
return null;
}, cancellationSignal);
}
OverviewCallbacks.get(launcher).onInitOverviewTransition();
launcher.deferOverlayCallbacksUntilNextResumeOrStop();
return mOnInitListener.test(launcher, alreadyOnHome);
}
@@ -0,0 +1,159 @@
/**
* 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.launcher3.uioverrides;
import static android.os.IBinder.FLAG_ONEWAY;
import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
import android.util.Log;
import androidx.annotation.MainThread;
import java.util.HashSet;
import java.util.Locale;
import java.util.function.BiConsumer;
import java.util.function.Supplier;
/**
* A binder proxy transaction listener for tracking non-whitelisted binder calls.
*/
public class DejankBinderTracker implements Binder.ProxyTransactListener {
private static final String TAG = "DejankBinderTracker";
private static final Object sLock = new Object();
private static final HashSet<String> sWhitelistedFrameworkClasses = new HashSet<>();
static {
// Common IPCs that are ok to block the main thread.
sWhitelistedFrameworkClasses.add("android.view.IWindowSession");
sWhitelistedFrameworkClasses.add("android.os.IPowerManager");
}
private static boolean sTemporarilyIgnoreTracking = false;
// Used by the client to limit binder tracking to specific regions
private static boolean sTrackingAllowed = false;
private BiConsumer<String, Integer> mUnexpectedTransactionCallback;
private boolean mIsTracking = false;
/**
* Temporarily ignore blocking binder calls for the duration of this {@link Runnable}.
*/
@MainThread
public static void whitelistIpcs(Runnable runnable) {
sTemporarilyIgnoreTracking = true;
runnable.run();
sTemporarilyIgnoreTracking = false;
}
/**
* Temporarily ignore blocking binder calls for the duration of this {@link Supplier}.
*/
@MainThread
public static <T> T whitelistIpcs(Supplier<T> supplier) {
sTemporarilyIgnoreTracking = true;
T value = supplier.get();
sTemporarilyIgnoreTracking = false;
return value;
}
/**
* Enables binder tracking during a test.
*/
@MainThread
public static void allowBinderTrackingInTests() {
sTrackingAllowed = true;
}
/**
* Disables binder tracking during a test.
*/
@MainThread
public static void disallowBinderTrackingInTests() {
sTrackingAllowed = false;
}
public DejankBinderTracker(BiConsumer<String, Integer> unexpectedTransactionCallback) {
mUnexpectedTransactionCallback = unexpectedTransactionCallback;
}
@MainThread
public void startTracking() {
if (Build.TYPE.toLowerCase(Locale.ROOT).contains("debug")
|| Build.TYPE.toLowerCase(Locale.ROOT).equals("eng")) {
Log.wtf(TAG, "Unexpected use of binder tracker in non-debug build", new Exception());
return;
}
if (mIsTracking) {
return;
}
mIsTracking = true;
Binder.setProxyTransactListener(this);
}
@MainThread
public void stopTracking() {
if (!mIsTracking) {
return;
}
mIsTracking = false;
Binder.setProxyTransactListener(null);
}
// Override the hidden Binder#onTransactStarted method
public synchronized Object onTransactStarted(IBinder binder, int transactionCode, int flags) {
if (!mIsTracking
|| !sTrackingAllowed
|| sTemporarilyIgnoreTracking
|| (flags & FLAG_ONEWAY) == FLAG_ONEWAY
|| !isMainThread()) {
return null;
}
String descriptor;
try {
descriptor = binder.getInterfaceDescriptor();
if (sWhitelistedFrameworkClasses.contains(descriptor)) {
return null;
}
} catch (RemoteException e) {
e.printStackTrace();
descriptor = binder.getClass().getSimpleName();
}
mUnexpectedTransactionCallback.accept(descriptor, transactionCode);
return null;
}
@Override
public Object onTransactStarted(IBinder binder, int transactionCode) {
// Do nothing
return null;
}
@Override
public void onTransactEnded(Object session) {
// Do nothing
}
public static boolean isMainThread() {
return Thread.currentThread() == Looper.getMainLooper().getThread();
}
}
@@ -18,7 +18,8 @@ package com.android.launcher3.uioverrides;
import android.content.Context;
import android.provider.DeviceConfig;
import com.android.launcher3.config.BaseFlags.BaseTogglableFlag;
import com.android.launcher3.config.FeatureFlags.BaseTogglableFlag;
public class TogglableFlag extends BaseTogglableFlag {
public static final String NAMESPACE_LAUNCHER = "launcher";
@@ -36,14 +37,14 @@ public class TogglableFlag extends BaseTogglableFlag {
@Override
public void addChangeListener(Context context, Runnable r) {
DeviceConfig.addOnPropertiesChangedListener(
NAMESPACE_LAUNCHER,
context.getMainExecutor(),
(properties) -> {
if (!NAMESPACE_LAUNCHER.equals(properties.getNamespace())) {
return;
}
initialize(context);
r.run();
});
NAMESPACE_LAUNCHER,
context.getMainExecutor(),
(properties) -> {
if (!NAMESPACE_LAUNCHER.equals(properties.getNamespace())) {
return;
}
initialize(context);
r.run();
});
}
}
@@ -14,16 +14,17 @@
package com.android.launcher3.uioverrides.plugins;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
import android.content.Context;
import android.os.Looper;
import com.android.launcher3.LauncherModel;
import com.android.systemui.shared.plugins.PluginInitializer;
public class PluginInitializerImpl implements PluginInitializer {
@Override
public Looper getBgLooper() {
return LauncherModel.getWorkerLooper();
return MODEL_EXECUTOR.getLooper();
}
@Override
@@ -97,6 +97,8 @@ public interface ActivityControlHelper<T extends BaseDraggingActivity> {
void onLaunchTaskSuccess(T activity);
default void closeOverlay() { }
interface ActivityInitListener {
void register();
@@ -157,6 +157,6 @@ public abstract class BaseRecentsActivity extends BaseDraggingActivity {
public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
super.dump(prefix, fd, writer, args);
writer.println(prefix + "Misc:");
dumpMisc(writer);
dumpMisc(prefix + "\t", writer);
}
}
@@ -1,43 +0,0 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.quickstep;
import android.content.Context;
import com.android.launcher3.R;
import com.android.launcher3.util.Preconditions;
import com.android.launcher3.util.ResourceBasedOverride;
/**
* Callbacks related to overview/quicksteps.
*/
public class OverviewCallbacks implements ResourceBasedOverride {
private static OverviewCallbacks sInstance;
public static OverviewCallbacks get(Context context) {
Preconditions.assertUIThread();
if (sInstance == null) {
sInstance = Overrides.getObject(OverviewCallbacks.class,
context.getApplicationContext(), R.string.overview_callbacks_class);
}
return sInstance;
}
public void onInitOverviewTransition() { }
public void closeAllWindows() { }
}
@@ -15,20 +15,21 @@
*/
package com.android.quickstep;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.os.RemoteException;
import android.util.Log;
import androidx.annotation.WorkerThread;
import com.android.launcher3.Utilities;
import com.android.launcher3.allapps.DiscoveryBounce;
import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.launcher3.util.UiThreadHelper;
import com.android.systemui.shared.recents.ISystemUiProxy;
import androidx.annotation.WorkerThread;
/**
* Sets alpha for the back button
*/
@@ -62,7 +63,7 @@ public class OverviewInteractionState {
// because of its high send frequency and data may be very different than the previous value
// For example, send back alpha on uihandler to avoid flickering when setting its visibility
mUiHandler = new Handler(this::handleUiMessage);
mBgHandler = new Handler(UiThreadHelper.getBackgroundLooper(), this::handleBgMessage);
mBgHandler = new Handler(UI_HELPER_EXECUTOR.getLooper(), this::handleBgMessage);
onNavigationModeChanged(SysUINavigationMode.INSTANCE.get(context)
.addModeChangeListener(this::onNavigationModeChanged));
@@ -16,19 +16,22 @@
package com.android.quickstep;
import static com.android.quickstep.TouchInteractionService.BACKGROUND_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import android.annotation.TargetApi;
import android.app.ActivityManager;
import android.content.Context;
import android.os.Build;
import android.os.Process;
import android.util.SparseBooleanArray;
import com.android.launcher3.MainThreadExecutor;
import androidx.annotation.VisibleForTesting;
import com.android.launcher3.util.LooperExecutor;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.KeyguardManagerCompat;
import com.android.systemui.shared.system.TaskStackChangeListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -41,7 +44,8 @@ import java.util.function.Consumer;
public class RecentTasksList extends TaskStackChangeListener {
private final KeyguardManagerCompat mKeyguardManager;
private final MainThreadExecutor mMainThreadExecutor;
private final LooperExecutor mMainThreadExecutor;
private final ActivityManagerWrapper mActivityManagerWrapper;
// The list change id, increments as the task list changes in the system
private int mChangeId;
@@ -52,11 +56,13 @@ public class RecentTasksList extends TaskStackChangeListener {
ArrayList<Task> mTasks = new ArrayList<>();
public RecentTasksList(Context context) {
mMainThreadExecutor = new MainThreadExecutor();
mKeyguardManager = new KeyguardManagerCompat(context);
public RecentTasksList(LooperExecutor mainThreadExecutor,
KeyguardManagerCompat keyguardManager, ActivityManagerWrapper activityManagerWrapper) {
mMainThreadExecutor = mainThreadExecutor;
mKeyguardManager = keyguardManager;
mChangeId = 1;
ActivityManagerWrapper.getInstance().registerTaskStackListener(this);
mActivityManagerWrapper = activityManagerWrapper;
mActivityManagerWrapper.registerTaskStackListener(this);
}
/**
@@ -64,7 +70,7 @@ public class RecentTasksList extends TaskStackChangeListener {
*/
public void getTaskKeys(int numTasks, Consumer<ArrayList<Task>> callback) {
// Kick off task loading in the background
BACKGROUND_EXECUTOR.execute(() -> {
UI_HELPER_EXECUTOR.execute(() -> {
ArrayList<Task> tasks = loadTasksInBackground(numTasks, true /* loadKeysOnly */);
mMainThreadExecutor.execute(() -> callback.accept(tasks));
});
@@ -86,12 +92,12 @@ public class RecentTasksList extends TaskStackChangeListener {
if (mLastLoadedId == mChangeId && (!mLastLoadHadKeysOnly || loadKeysOnly)) {
// The list is up to date, send the callback on the next frame,
// so that requestID can be returned first.
mMainThreadExecutor.getHandler().post(resultCallback);
mMainThreadExecutor.post(resultCallback);
return requestLoadId;
}
// Kick off task loading in the background
BACKGROUND_EXECUTOR.execute(() -> {
UI_HELPER_EXECUTOR.execute(() -> {
ArrayList<Task> tasks = loadTasksInBackground(Integer.MAX_VALUE, loadKeysOnly);
mMainThreadExecutor.execute(() -> {
@@ -136,12 +142,13 @@ public class RecentTasksList extends TaskStackChangeListener {
/**
* Loads and creates a list of all the recent tasks.
*/
private ArrayList<Task> loadTasksInBackground(int numTasks,
@VisibleForTesting
ArrayList<Task> loadTasksInBackground(int numTasks,
boolean loadKeysOnly) {
int currentUserId = Process.myUserHandle().getIdentifier();
ArrayList<Task> allTasks = new ArrayList<>();
List<ActivityManager.RecentTaskInfo> rawTasks =
ActivityManagerWrapper.getInstance().getRecentTasks(numTasks, currentUserId);
mActivityManagerWrapper.getRecentTasks(numTasks, currentUserId);
// The raw tasks are given in most-recent to least-recent order, we need to reverse it
Collections.reverse(rawTasks);
@@ -15,6 +15,8 @@
*/
package com.android.quickstep;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
@@ -22,7 +24,6 @@ import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import com.android.launcher3.MainThreadExecutor;
import com.android.quickstep.ActivityControlHelper.ActivityInitListener;
import com.android.quickstep.util.RemoteAnimationProvider;
@@ -92,14 +93,10 @@ public class RecentsActivityTracker<T extends BaseRecentsActivity> implements Ac
private static class Scheduler implements Runnable {
private WeakReference<RecentsActivityTracker> mPendingTracker = new WeakReference<>(null);
private MainThreadExecutor mMainThreadExecutor;
public synchronized void schedule(RecentsActivityTracker tracker) {
mPendingTracker = new WeakReference<>(tracker);
if (mMainThreadExecutor == null) {
mMainThreadExecutor = new MainThreadExecutor();
}
mMainThreadExecutor.execute(this);
MAIN_EXECUTOR.execute(this);
}
@Override
@@ -15,6 +15,10 @@
*/
package com.android.quickstep;
import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.createAndStartNewLooper;
import static com.android.quickstep.TaskUtils.checkCurrentOrManagedUserId;
import android.annotation.TargetApi;
@@ -22,16 +26,20 @@ import android.app.ActivityManager;
import android.content.ComponentCallbacks2;
import android.content.Context;
import android.os.Build;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Log;
import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.compat.LauncherAppsCompat.OnAppsChangedCallbackCompat;
import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.systemui.shared.recents.ISystemUiProxy;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.KeyguardManagerCompat;
import com.android.systemui.shared.system.TaskStackChangeListener;
import java.util.ArrayList;
@@ -61,13 +69,14 @@ public class RecentsModel extends TaskStackChangeListener {
private RecentsModel(Context context) {
mContext = context;
HandlerThread loaderThread = new HandlerThread("TaskThumbnailIconCache",
Process.THREAD_PRIORITY_BACKGROUND);
loaderThread.start();
mTaskList = new RecentTasksList(context);
mIconCache = new TaskIconCache(context, loaderThread.getLooper());
mThumbnailCache = new TaskThumbnailCache(context, loaderThread.getLooper());
Looper looper =
createAndStartNewLooper("TaskThumbnailIconCache", THREAD_PRIORITY_BACKGROUND);
mTaskList = new RecentTasksList(MAIN_EXECUTOR,
new KeyguardManagerCompat(context), ActivityManagerWrapper.getInstance());
mIconCache = new TaskIconCache(context, looper);
mThumbnailCache = new TaskThumbnailCache(context, looper);
ActivityManagerWrapper.getInstance().registerTaskStackListener(this);
setupPackageListener();
}
public TaskIconCache getIconCache() {
@@ -166,6 +175,7 @@ public class RecentsModel extends TaskStackChangeListener {
public void onTaskRemoved(int taskId) {
Task.TaskKey dummyKey = new Task.TaskKey(taskId, 0, null, null, 0, 0);
mThumbnailCache.remove(dummyKey);
mIconCache.onTaskRemoved(dummyKey);
}
public void setSystemUiProxy(ISystemUiProxy systemUiProxy) {
@@ -200,6 +210,21 @@ public class RecentsModel extends TaskStackChangeListener {
}
}
private void setupPackageListener() {
LauncherAppsCompat.getInstance(mContext)
.addOnAppsChangedCallback(new OnAppsChangedCallbackCompat() {
@Override
public void onPackageRemoved(String packageName, UserHandle user) {
mIconCache.invalidatePackage(packageName);
}
@Override
public void onPackageChanged(String packageName, UserHandle user) {
mIconCache.invalidatePackage(packageName);
}
});
}
public void addThumbnailChangeListener(TaskThumbnailChangeListener listener) {
mThumbnailChangeListeners.add(listener);
}
@@ -16,6 +16,7 @@
package com.android.quickstep;
import static com.android.launcher3.uioverrides.RecentsUiFactory.GO_LOW_RAM_RECENTS_ENABLED;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import android.content.ComponentName;
import android.content.Context;
@@ -27,26 +28,25 @@ import android.os.Looper;
import android.util.LruCache;
import android.view.accessibility.AccessibilityManager;
import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.icons.cache.HandlerRunnable;
import com.android.launcher3.uioverrides.RecentsUiFactory;
import com.android.launcher3.util.Preconditions;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.Task.TaskKey;
import com.android.systemui.shared.recents.model.TaskKeyLruCache;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import java.util.Map;
import java.util.function.Consumer;
/**
* Manages the caching of task icons and related data.
* TODO: This class should later be merged into IconCache.
* TODO(b/138944598): This class should later be merged into IconCache.
*/
public class TaskIconCache {
private final Handler mBackgroundHandler;
private final MainThreadExecutor mMainThreadExecutor;
private final AccessibilityManager mAccessibilityManager;
private final NormalizedIconLoader mIconLoader;
@@ -67,7 +67,6 @@ public class TaskIconCache {
public TaskIconCache(Context context, Looper backgroundLooper) {
mBackgroundHandler = new Handler(backgroundLooper);
mMainThreadExecutor = new MainThreadExecutor();
mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
Resources res = context.getResources();
@@ -103,7 +102,7 @@ public class TaskIconCache {
// We don't call back to the provided callback in this case
return;
}
mMainThreadExecutor.execute(() -> {
MAIN_EXECUTOR.execute(() -> {
task.icon = icon;
task.titleDescription = contentDescription;
callback.accept(task);
@@ -149,6 +148,21 @@ public class TaskIconCache {
return label;
}
void onTaskRemoved(TaskKey taskKey) {
mIconCache.remove(taskKey);
}
void invalidatePackage(String packageName) {
// TODO(b/138944598): Merge this class into IconCache so we can do this at the base level
Map<ComponentName, ActivityInfo> activityInfoCache = mActivityInfoCache.snapshot();
for (ComponentName cn : activityInfoCache.keySet()) {
if (cn.getPackageName().equals(packageName)) {
mActivityInfoCache.remove(cn);
}
}
}
public static abstract class IconLoadRequest extends HandlerRunnable {
IconLoadRequest(Handler handler) {
super(handler, null);
@@ -15,12 +15,14 @@
*/
package com.android.quickstep;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import android.app.ActivityManager;
import android.content.Context;
import android.content.res.Resources;
import android.os.Handler;
import android.os.Looper;
import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.icons.cache.HandlerRunnable;
@@ -30,13 +32,13 @@ import com.android.systemui.shared.recents.model.Task.TaskKey;
import com.android.systemui.shared.recents.model.TaskKeyLruCache;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import java.util.ArrayList;
import java.util.function.Consumer;
public class TaskThumbnailCache {
private final Handler mBackgroundHandler;
private final MainThreadExecutor mMainThreadExecutor;
private final int mCacheSize;
private final ThumbnailCache mCache;
@@ -94,7 +96,6 @@ public class TaskThumbnailCache {
public TaskThumbnailCache(Context context, Looper backgroundLooper) {
mBackgroundHandler = new Handler(backgroundLooper);
mMainThreadExecutor = new MainThreadExecutor();
mHighResLoadingState = new HighResLoadingState(context);
Resources res = context.getResources();
@@ -168,7 +169,7 @@ public class TaskThumbnailCache {
// We don't call back to the provided callback in this case
return;
}
mMainThreadExecutor.execute(() -> {
MAIN_EXECUTOR.execute(() -> {
mCache.put(key, thumbnail);
callback.accept(thumbnail);
onEnd();
@@ -150,10 +150,10 @@ public class AppPredictionsUITests extends AbstractQuickStepTest {
List<AppTarget> targets = new ArrayList<>(activities.length);
for (LauncherActivityInfo info : activities) {
ComponentName cn = info.getComponentName();
AppTarget target =
new AppTarget.Builder(new AppTargetId("app:" + cn), cn.getPackageName(), info.getUser())
.setClassName(cn.getClassName())
.build();
AppTarget target = new AppTarget.Builder(
new AppTargetId("app:" + cn), cn.getPackageName(), info.getUser())
.setClassName(cn.getClassName())
.build();
targets.add(target);
}
mCallback.onTargetsAvailable(targets);
@@ -22,11 +22,18 @@ import static androidx.test.InstrumentationRegistry.getInstrumentation;
import static com.android.launcher3.tapl.LauncherInstrumentation.WAIT_TIME_MS;
import static com.android.launcher3.tapl.TestHelpers.getHomeIntentInPackage;
import static com.android.launcher3.tapl.TestHelpers.getLauncherInMyProcess;
import static com.android.launcher3.ui.AbstractLauncherUiTest.DEFAULT_UI_TIMEOUT;
import static com.android.launcher3.ui.AbstractLauncherUiTest.resolveSystemApp;
import static com.android.launcher3.ui.AbstractLauncherUiTest.startAppFast;
import static com.android.launcher3.ui.AbstractLauncherUiTest.startTestActivity;
import static com.android.launcher3.ui.TaplTestsLauncher3.getAppPackageName;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.rule.ShellCommandRule.disableHeadsUpNotification;
import static com.android.launcher3.util.rule.ShellCommandRule.getLauncherCommand;
import static com.android.quickstep.NavigationModeSwitchRule.Mode.THREE_BUTTON;
import static com.android.quickstep.NavigationModeSwitchRule.Mode.ZERO_BUTTON;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import android.app.Instrumentation;
@@ -41,10 +48,16 @@ import androidx.test.uiautomator.By;
import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.Until;
import com.android.launcher3.Utilities;
import com.android.launcher3.tapl.BaseOverview;
import com.android.launcher3.tapl.LauncherInstrumentation;
import com.android.launcher3.tapl.OverviewTask;
import com.android.launcher3.tapl.TestHelpers;
import com.android.launcher3.testcomponent.TestCommandReceiver;
import com.android.launcher3.util.rule.FailureWatcher;
import com.android.launcher3.util.rule.SimpleActivityRule;
import com.android.quickstep.NavigationModeSwitchRule.NavigationModeSwitch;
import com.android.quickstep.views.RecentsView;
import org.junit.Rule;
import org.junit.Test;
@@ -53,11 +66,11 @@ import org.junit.rules.TestRule;
import org.junit.runner.RunWith;
import org.junit.runners.model.Statement;
import java.util.function.Consumer;
import java.util.function.Function;
@LargeTest
@RunWith(AndroidJUnit4.class)
/**
* TODO: Fix fallback when quickstep is enabled
*/
public class FallbackRecentsTest {
private final UiDevice mDevice;
@@ -73,6 +86,11 @@ public class FallbackRecentsTest {
@Rule
public final TestRule mOrderSensitiveRules;
@Rule
public final SimpleActivityRule<RecentsActivity> mActivityMonitor =
new SimpleActivityRule(RecentsActivity.class);
public FallbackRecentsTest() throws RemoteException {
Instrumentation instrumentation = getInstrumentation();
Context context = instrumentation.getContext();
@@ -80,9 +98,12 @@ public class FallbackRecentsTest {
mDevice.setOrientationNatural();
mLauncher = new LauncherInstrumentation(instrumentation);
mOrderSensitiveRules = RuleChain.
outerRule(new NavigationModeSwitchRule(mLauncher)).
around(new FailureWatcher(mDevice));
if (TestHelpers.isInLauncherProcess()) {
Utilities.enableRunningInTestHarnessForTests();
}
mOrderSensitiveRules = RuleChain.outerRule(new NavigationModeSwitchRule(mLauncher))
.around(new FailureWatcher(mDevice));
mOtherLauncherActivity = context.getPackageManager().queryIntentActivities(
getHomeIntentInPackage(context),
@@ -105,7 +126,7 @@ public class FallbackRecentsTest {
};
}
@NavigationModeSwitch(mode = THREE_BUTTON)
@NavigationModeSwitch
@Test
public void goToOverviewFromHome() {
mDevice.pressHome();
@@ -115,7 +136,7 @@ public class FallbackRecentsTest {
mLauncher.getBackground().switchToOverview();
}
@NavigationModeSwitch(mode = THREE_BUTTON)
@NavigationModeSwitch
@Test
public void goToOverviewFromApp() {
startAppFast(resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR));
@@ -123,15 +144,77 @@ public class FallbackRecentsTest {
mLauncher.getBackground().switchToOverview();
}
private void startAppFast(String packageName) {
final Instrumentation instrumentation = getInstrumentation();
final Intent intent = instrumentation.getContext().getPackageManager().
getLaunchIntentForPackage(packageName);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
instrumentation.getTargetContext().startActivity(intent);
assertTrue(packageName + " didn't start",
mDevice.wait(Until.hasObject(By.pkg(packageName).depth(0)), WAIT_TIME_MS));
protected void executeOnRecents(Consumer<RecentsActivity> f) throws Exception {
getFromRecents(r -> {
f.accept(r);
return null;
});
}
protected <T> T getFromRecents(Function<RecentsActivity, T> f) throws Exception {
if (!TestHelpers.isInLauncherProcess()) return null;
return MAIN_EXECUTOR.submit(() -> f.apply(mActivityMonitor.getActivity())).get();
}
private BaseOverview pressHomeAndGoToOverview() {
mDevice.pressHome();
return mLauncher.getBackground().switchToOverview();
}
// TODO: Enable all modes after b/141184247 is fixed
@NavigationModeSwitch(mode = ZERO_BUTTON)
@Test
public void testOverview() throws Exception {
startAppFast(getAppPackageName());
startAppFast(resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR));
startTestActivity(2);
BaseOverview overview = mLauncher.getBackground().switchToOverview();
executeOnRecents(
recents -> assertTrue("Don't have at least 3 tasks", getTaskCount(recents) >= 3));
// Test flinging forward and backward.
overview.flingForward();
final Integer currentTaskAfterFlingForward = getFromRecents(this::getCurrentOverviewPage);
executeOnRecents(recents -> assertTrue("Current task in Overview is still 0",
currentTaskAfterFlingForward > 0));
overview.flingBackward();
executeOnRecents(recents -> assertTrue("Flinging back in Overview did nothing",
getCurrentOverviewPage(recents) < currentTaskAfterFlingForward));
// Test opening a task.
overview = pressHomeAndGoToOverview();
OverviewTask task = overview.getCurrentTask();
assertNotNull("overview.getCurrentTask() returned null (1)", task);
assertNotNull("OverviewTask.open returned null", task.open());
assertTrue("Test activity didn't open from Overview", mDevice.wait(Until.hasObject(
By.pkg(getAppPackageName()).text("TestActivity2")),
DEFAULT_UI_TIMEOUT));
// Test dismissing a task.
overview = pressHomeAndGoToOverview();
final Integer numTasks = getFromRecents(this::getTaskCount);
task = overview.getCurrentTask();
assertNotNull("overview.getCurrentTask() returned null (2)", task);
task.dismiss();
executeOnRecents(
recents -> assertEquals("Dismissing a task didn't remove 1 task from Overview",
numTasks - 1, getTaskCount(recents)));
// Test dismissing all tasks.
pressHomeAndGoToOverview().dismissAllTasks();
assertTrue("Fallback Launcher not visible", mDevice.wait(Until.hasObject(By.pkg(
mOtherLauncherActivity.packageName)), WAIT_TIME_MS));
}
private int getCurrentOverviewPage(RecentsActivity recents) {
return recents.<RecentsView>getOverviewPanel().getCurrentPage();
}
private int getTaskCount(RecentsActivity recents) {
return recents.<RecentsView>getOverviewPanel().getTaskViewCount();
}
}
@@ -0,0 +1,99 @@
/*
* 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.quickstep;
import static junit.framework.TestCase.assertNull;
import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.ActivityManager;
import androidx.test.filters.SmallTest;
import com.android.launcher3.util.LooperExecutor;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.KeyguardManagerCompat;
import org.junit.Before;
import org.junit.Test;
import java.util.Collections;
import java.util.List;
@SmallTest
public class RecentTasksListTest {
private ActivityManagerWrapper mockActivityManagerWrapper;
// Class under test
private RecentTasksList mRecentTasksList;
@Before
public void setup() {
LooperExecutor mockMainThreadExecutor = mock(LooperExecutor.class);
KeyguardManagerCompat mockKeyguardManagerCompat = mock(KeyguardManagerCompat.class);
mockActivityManagerWrapper = mock(ActivityManagerWrapper.class);
mRecentTasksList = new RecentTasksList(mockMainThreadExecutor, mockKeyguardManagerCompat,
mockActivityManagerWrapper);
}
@Test
public void onTaskRemoved_reloadsAllTasks() {
mRecentTasksList.onTaskRemoved(0);
verify(mockActivityManagerWrapper, times(1))
.getRecentTasks(anyInt(), anyInt());
}
@Test
public void onTaskStackChanged_doesNotFetchTasks() {
mRecentTasksList.onTaskStackChanged();
verify(mockActivityManagerWrapper, times(0))
.getRecentTasks(anyInt(), anyInt());
}
@Test
public void loadTasksInBackground_onlyKeys_noValidTaskDescription() {
ActivityManager.RecentTaskInfo recentTaskInfo = new ActivityManager.RecentTaskInfo();
when(mockActivityManagerWrapper.getRecentTasks(anyInt(), anyInt()))
.thenReturn(Collections.singletonList(recentTaskInfo));
List<Task> taskList = mRecentTasksList.loadTasksInBackground(Integer.MAX_VALUE, true);
assertEquals(1, taskList.size());
assertNull(taskList.get(0).taskDescription.getLabel());
}
@Test
public void loadTasksInBackground_moreThanKeys_hasValidTaskDescription() {
String taskDescription = "Wheeee!";
ActivityManager.RecentTaskInfo recentTaskInfo = new ActivityManager.RecentTaskInfo();
recentTaskInfo.taskDescription = new ActivityManager.TaskDescription(taskDescription);
when(mockActivityManagerWrapper.getRecentTasks(anyInt(), anyInt()))
.thenReturn(Collections.singletonList(recentTaskInfo));
List<Task> taskList = mRecentTasksList.loadTasksInBackground(Integer.MAX_VALUE, false);
assertEquals(1, taskList.size());
assertEquals(taskDescription, taskList.get(0).taskDescription.getLabel());
}
}
+1
View File
@@ -20,4 +20,5 @@
style="@style/BaseIcon"
android:textColor="?attr/folderTextColor"
android:includeFontPadding="false"
android:hapticFeedbackEnabled="false"
launcher:iconDisplay="folder" />
-1
View File
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"ስራ"</string>
<string name="activity_not_found" msgid="8071924732094499514">"መተግበሪያ አልተጫነም።"</string>
<string name="activity_not_available" msgid="7456344436509528827">"መተግበሪያ አይገኝም"</string>
-1
View File
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"İş"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Tətbiq quraşdırılmayıb."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Tətbiq əlçatmazdır"</string>
-1
View File
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"কাজ"</string>
<string name="activity_not_found" msgid="8071924732094499514">"অ্যাপ্লিকেশান ইনস্টল করা নেই৷"</string>
<string name="activity_not_available" msgid="7456344436509528827">"অ্যাপ্লিকেশান অনুপলব্ধ"</string>
-1
View File
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Posao"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Aplikacija nije instalirana."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Aplikacija nije dostupna"</string>
-1
View File
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Feina"</string>
<string name="activity_not_found" msgid="8071924732094499514">"L\'aplicació no s\'ha instal·lat."</string>
<string name="activity_not_available" msgid="7456344436509528827">"L\'aplicació no està disponible."</string>
-1
View File
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Εργασία"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Η εφαρμογή δεν έχει εγκατασταθεί."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Η εφαρμογή δεν είναι διαθέσιμη"</string>
-1
View File
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Work"</string>
<string name="activity_not_found" msgid="8071924732094499514">"App isn\'t installed."</string>
<string name="activity_not_available" msgid="7456344436509528827">"App isn\'t available"</string>
-1
View File
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Work"</string>
<string name="activity_not_found" msgid="8071924732094499514">"App isn\'t installed."</string>
<string name="activity_not_available" msgid="7456344436509528827">"App isn\'t available"</string>
-1
View File
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Work"</string>
<string name="activity_not_found" msgid="8071924732094499514">"App isn\'t installed."</string>
<string name="activity_not_available" msgid="7456344436509528827">"App isn\'t available"</string>
-1
View File
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Lana"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Aplikazioa instalatu gabe dago."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Ez dago erabilgarri aplikazioa"</string>
+1 -2
View File
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Android Work"</string>
<string name="activity_not_found" msgid="8071924732094499514">"L\'application n\'est pas installée."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Application indisponible"</string>
@@ -136,7 +135,7 @@
<string name="bottom_work_tab_user_education_title" msgid="5785851780786322825">"Retrouvez ici vos applications professionnelles"</string>
<string name="bottom_work_tab_user_education_body" msgid="2818107472360579152">"Les applications professionnelles sont accompagnées d\'un badge et sont sécurisées par votre organisation. Vous pouvez les déplacer vers votre écran d\'accueil pour y accéder plus facilement."</string>
<string name="work_mode_on_label" msgid="4781128097185272916">"Géré par votre organisation"</string>
<string name="work_mode_off_label" msgid="3194894777601421047">"Les notifications et les applications sont désactivées"</string>
<string name="work_mode_off_label" msgid="3194894777601421047">"Notifications et applications désactivées"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Fermer"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Fermé"</string>
<string name="remote_action_failed" msgid="1383965239183576790">"Échec : <xliff:g id="WHAT">%1$s</xliff:g>"</string>
-1
View File
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Traballo"</string>
<string name="activity_not_found" msgid="8071924732094499514">"A aplicación non está instalada"</string>
<string name="activity_not_available" msgid="7456344436509528827">"A aplicación non está dispoñible"</string>
-1
View File
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"કાર્યાલય"</string>
<string name="activity_not_found" msgid="8071924732094499514">"ઍપ્લિકેશન ઇન્સ્ટોલ થઈ નથી."</string>
<string name="activity_not_available" msgid="7456344436509528827">"ઍપ્લિકેશન ઉપલબ્ધ નથી"</string>
-1
View File
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"कार्यस्‍थल"</string>
<string name="activity_not_found" msgid="8071924732094499514">"ऐप्‍लिकेशन इंस्‍टॉल नहीं है."</string>
<string name="activity_not_available" msgid="7456344436509528827">"ऐप्लिकेशन उपलब्ध नहीं है"</string>
-1
View File
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Posao"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Aplikacija nije instalirana."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Aplikacija nije dostupna"</string>
+1 -2
View File
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Աշխատանքային"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Ծրագիրը տեղադրված չէ:"</string>
<string name="activity_not_available" msgid="7456344436509528827">"Հավելվածը հասանելի չէ"</string>
@@ -87,7 +86,7 @@
<string name="allow_rotation_desc" msgid="8662546029078692509">"Հեռախոսը պտտելու դեպքում"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"Ծանուցումների կետիկներ"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"Միացված է"</string>
<string name="notification_dots_desc_off" msgid="1760796511504341095">"Անջատած է"</string>
<string name="notification_dots_desc_off" msgid="1760796511504341095">"Անջատված է"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Անհրաժեշտ է ծանուցման թույլտվություն"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Ծանուցումների կետիկները ցուցադրելու համար միացրեք ծանուցումները <xliff:g id="NAME">%1$s</xliff:g>-ի համար"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Փոխել կարգավորումները"</string>
-1
View File
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Kantor"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Aplikasi tidak dipasang."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Aplikasi tidak tersedia"</string>
-1
View File
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"ការងារ"</string>
<string name="activity_not_found" msgid="8071924732094499514">"មិន​បាន​ដំឡើង​កម្មវិធី។"</string>
<string name="activity_not_available" msgid="7456344436509528827">"មិន​មាន​កម្មវិធី"</string>
-1
View File
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"ಕೆಲಸ"</string>
<string name="activity_not_found" msgid="8071924732094499514">"ಅಪ್ಲಿಕೇಶನ್‌ ಅನ್ನು ಸ್ಥಾಪಿಸಲಾಗಿಲ್ಲ"</string>
<string name="activity_not_available" msgid="7456344436509528827">"ಅಪ್ಲಿಕೇಶನ್ ಲಭ್ಯವಿಲ್ಲ"</string>
-1
View File
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Жумуш"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Колдонмо орнотулган эмес."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Колдонмо жеткиликтүү эмес"</string>
-1
View File
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Стартер3"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Работа"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Апликацијата не е инсталирана."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Апликацијата не е достапна"</string>
-1
View File
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"ဖွင့်တင်စက်၃"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"အလုပ်"</string>
<string name="activity_not_found" msgid="8071924732094499514">"အက်ပ်မထည့်သွင်းထားပါ"</string>
<string name="activity_not_available" msgid="7456344436509528827">"အက်ပ်လက်လှမ်း မမှီပါ"</string>
-1
View File
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Trabalho"</string>
<string name="activity_not_found" msgid="8071924732094499514">"A aplicação não está instalada."</string>
<string name="activity_not_available" msgid="7456344436509528827">"A aplicação não está disponível"</string>
-1
View File
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Tela de início 3"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Trabalho"</string>
<string name="activity_not_found" msgid="8071924732094499514">"O app não está instalado."</string>
<string name="activity_not_available" msgid="7456344436509528827">"O app não está disponível"</string>
-1
View File
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Work"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Aplicația nu este instalată."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Aplicația nu este disponibilă"</string>
-1
View File
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Pracovné"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Aplikácia nie je nainštalovaná."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Aplikácia nie je k dispozícii"</string>
+2 -3
View File
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Nisësi3"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Puna"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Aplikacioni nuk është i instaluar."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Aplikacioni nuk mundësohet"</string>
@@ -41,8 +40,8 @@
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Kërko për më shumë aplikacione"</string>
<string name="label_application" msgid="8531721983832654978">"Aplikacioni"</string>
<string name="notifications_header" msgid="1404149926117359025">"Njoftimet"</string>
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Prek dhe mbaj prekur për të zgjedhur një shkurtore."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Prek dy herë dhe mbaj prekur për të zgjedhur një shkurtore ose për të përdorur veprimet e personalizuara."</string>
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Prek dhe mbaj të shtypur për të zgjedhur një shkurtore."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Prek dy herë dhe mbaj të shtypur për të zgjedhur një shkurtore ose për të përdorur veprimet e personalizuara."</string>
<string name="out_of_space" msgid="4691004494942118364">"Nuk ka më hapësirë në këtë ekran bazë."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Nuk ka më hapësirë në tabakanë \"Të preferuarat\""</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Lista e aplikacioneve"</string>
-1
View File
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Kazini"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Programu haijasakinishwa."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Programu haipatikani"</string>
+2 -3
View File
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"பணியிடம்"</string>
<string name="activity_not_found" msgid="8071924732094499514">"ஆப்ஸ் நிறுவப்படவில்லை."</string>
<string name="activity_not_available" msgid="7456344436509528827">"ஆப்ஸ் இல்லை"</string>
@@ -36,7 +35,7 @@
<string name="add_item_request_drag_hint" msgid="5899764264480397019">"நீங்களே சேர்க்க, தொட்டுப் பிடித்திருக்கவும்"</string>
<string name="place_automatically" msgid="8064208734425456485">"தானாகவே சேர்"</string>
<string name="all_apps_search_bar_hint" msgid="1390553134053255246">"பயன்பாடுகளில் தேடுக"</string>
<string name="all_apps_loading_message" msgid="5813968043155271636">"பயன்பாடுகளை ஏற்றுகிறது…"</string>
<string name="all_apps_loading_message" msgid="5813968043155271636">"ஆப்ஸை ஏற்றுகிறது…"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"\"<xliff:g id="QUERY">%1$s</xliff:g>\" உடன் பொருந்தும் பயன்பாடுகள் இல்லை"</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"கூடுதல் பயன்பாடுகளைத் தேடு"</string>
<string name="label_application" msgid="8531721983832654978">"ஆப்ஸ்"</string>
@@ -45,7 +44,7 @@
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"ஷார்ட்கட்டைச் சேர்க்க, இருமுறை தட்டிப் பிடித்திருக்கவும் (அ) தனிப்பயன் செயல்களைப் பயன்படுத்தவும்."</string>
<string name="out_of_space" msgid="4691004494942118364">"முகப்புத் திரையில் இடமில்லை."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"பிடித்தவை ட்ரேயில் இடமில்லை"</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"பயன்பாடுகளின் பட்டியல்"</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"ஆப்ஸின் பட்டியல்"</string>
<string name="all_apps_button_personal_label" msgid="1315764287305224468">"தனிப்பட்ட ஆப்ஸ் பட்டியல்"</string>
<string name="all_apps_button_work_label" msgid="7270707118948892488">"பணி ஆப்ஸ் பட்டியல்"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"முகப்பு"</string>
+1 -2
View File
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"కార్యాలయం"</string>
<string name="activity_not_found" msgid="8071924732094499514">"యాప్ ఇన్‌స్టాల్ చేయబడలేదు."</string>
<string name="activity_not_available" msgid="7456344436509528827">"యాప్ అందుబాటులో లేదు"</string>
@@ -53,7 +52,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"అన్ఇన్‌స్టాల్ చేయి"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"యాప్ సమాచారం"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"ఇన్‌స్టాల్ చేయండి"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"సత్వరమార్గాలను ఇన్‌స్టాల్ చేయడం"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"షార్ట్‌కట్‌లను ఇన్‌స్టాల్ చేయడం"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"వినియోగదారు ప్రమేయం లేకుండా సత్వరమార్గాలను జోడించడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"హోమ్ సెట్టింగ్‌లు మరియు సత్వరమార్గాలను చదవడం"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"హోమ్‌లో సెట్టింగ్‌లు మరియు సత్వరమార్గాలను చదవడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
-1
View File
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"งาน"</string>
<string name="activity_not_found" msgid="8071924732094499514">"ไม่ได้ติดตั้งแอป"</string>
<string name="activity_not_available" msgid="7456344436509528827">"แอปไม่พร้อมใช้งาน"</string>
-1
View File
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Isiqalisi3"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Umsebenzi"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Uhlelo lokusebenza alufakiwe."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Uhlelo lokusebenza alutholakali"</string>
+8 -16
View File
@@ -115,7 +115,8 @@
<attr name="numFolderColumns" format="integer" />
<!-- numHotseatIcons defaults to numColumns, if not specified -->
<attr name="numHotseatIcons" format="integer" />
<!-- numAllAppsColumns defaults to numColumns, if not specified -->
<attr name="numAllAppsColumns" format="integer" />
<attr name="defaultLayoutId" format="reference" />
<attr name="demoModeLayoutId" format="reference" />
</declare-styleable>
@@ -131,6 +132,12 @@
<attr name="iconTextSize" format="float" />
<!-- If true, this display option is used to determine the default grid -->
<attr name="canBeDefault" format="boolean" />
<!-- The following values are only enabled if grid is supported. -->
<!-- allAppsIconSize defaults to iconSize, if not specified -->
<attr name="allAppsIconSize" format="float" />
<!-- allAppsIconTextSize defaults to iconTextSize, if not specified -->
<attr name="allAppsIconTextSize" format="float" />
</declare-styleable>
<declare-styleable name="CellLayout">
@@ -152,21 +159,6 @@
<attr name="canThumbDetach" format="boolean" />
</declare-styleable>
<declare-styleable name="CustomAppWidgetProviderInfo">
<attr name="providerId" format="integer" />
<attr name="android:label" />
<attr name="android:initialLayout" />
<attr name="android:icon" />
<attr name="android:previewImage" />
<attr name="android:resizeMode" />
<attr name="numRows" />
<attr name="numColumns" />
<attr name="numMinRows" format="integer" />
<attr name="numMinColumns" format="integer" />
</declare-styleable>
<declare-styleable name="PreviewFragment">
<attr name="android:name" />
<attr name="android:id" />
+3 -2
View File
@@ -23,8 +23,6 @@
<!-- Application name -->
<string name="app_name">Launcher3</string>
<!-- Default folder name -->
<string name="folder_name"></string>
<!-- Work folder name -->
<string name="work_folder_name">Work</string>
<!-- Displayed when user selects a shortcut for an app that was uninstalled [CHAR_LIMIT=none]-->
@@ -105,6 +103,9 @@
<!-- Label for install drop target. [CHAR_LIMIT=20] -->
<string name="install_drop_target_label">Install</string>
<!-- Label for install dismiss prediction. -->
<string translatable="false" name="dismiss_prediction_label">Dismiss prediction</string>
<!-- Permissions: -->
<skip />
<!-- Permission short label -->
-31
View File
@@ -1,31 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017 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.
-->
<widgets>
<!-- Sample widget definition
<widget
android:label="My custom widget"
android:initialLayout="@layout/sample_widget_layout"
android:icon="@drawable/ic_launcher_home"
android:resizeMode="horizontal|vertical"
launcher:numRows="2"
launcher:numColumns="3"
launcher:numMinRows="1"
launcher:numMinColumns="2"
launcher:providerId="1" />
-->
</widgets>

Some files were not shown because too many files have changed in this diff Show More