Merge changes Ie48f4b66,Ia48f4453 into ub-launcher3-master
* changes:
Always update clip rect before applying surface params
Clean up AppWindowAnimationHelper and TransformParams
diff --git a/go/src/com/android/launcher3/model/WidgetsModel.java b/go/src/com/android/launcher3/model/WidgetsModel.java
index 7690b9d..3b3dc01 100644
--- a/go/src/com/android/launcher3/model/WidgetsModel.java
+++ b/go/src/com/android/launcher3/model/WidgetsModel.java
@@ -16,6 +16,7 @@
package com.android.launcher3.model;
+import android.content.ComponentName;
import android.content.Context;
import android.os.UserHandle;
@@ -68,4 +69,9 @@
public void onPackageIconsUpdated(Set<String> packageNames, UserHandle user,
LauncherAppState app) {
}
+
+ public WidgetItem getWidgetProviderInfoByProviderName(
+ ComponentName providerName) {
+ return null;
+ }
}
\ No newline at end of file
diff --git a/protos/launcher_trace.proto b/protos/launcher_trace.proto
new file mode 100644
index 0000000..c6f3543
--- /dev/null
+++ b/protos/launcher_trace.proto
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+syntax = "proto2";
+
+package com.android.launcher3.tracing;
+
+option java_multiple_files = true;
+
+message LauncherTraceProto {
+
+ optional TouchInteractionServiceProto touch_interaction_service = 1;
+}
+
+message TouchInteractionServiceProto {
+
+ optional bool service_connected = 1;
+}
diff --git a/protos/launcher_trace_file.proto b/protos/launcher_trace_file.proto
new file mode 100644
index 0000000..6ce182a
--- /dev/null
+++ b/protos/launcher_trace_file.proto
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+
+syntax = "proto2";
+
+import "launcher_trace.proto";
+
+package com.android.launcher3.tracing;
+
+option java_multiple_files = true;
+
+/* represents a file full of launcher trace entries.
+ Encoded, it should start with 0x9 0x4C 0x4E 0x43 0x48 0x52 0x54 0x52 0x43 (.LNCHRTRC), such
+ that they can be easily identified. */
+message LauncherTraceFileProto {
+
+ /* constant; MAGIC_NUMBER = (long) MAGIC_NUMBER_H << 32 | MagicNumber.MAGIC_NUMBER_L
+ (this is needed because enums have to be 32 bits and there's no nice way to put 64bit
+ constants into .proto files. */
+ enum MagicNumber {
+ INVALID = 0;
+ MAGIC_NUMBER_L = 0x48434E4C; /* LNCH (little-endian ASCII) */
+ MAGIC_NUMBER_H = 0x43525452; /* RTRC (little-endian ASCII) */
+ }
+
+ optional fixed64 magic_number = 1; /* Must be the first field, set to value in MagicNumber */
+ repeated LauncherTraceEntryProto entry = 2;
+}
+
+/* one launcher trace entry. */
+message LauncherTraceEntryProto {
+ /* required: elapsed realtime in nanos since boot of when this entry was logged */
+ optional fixed64 elapsed_realtime_nanos = 1;
+
+ optional LauncherTraceProto launcher = 3;
+}
diff --git a/quickstep/AndroidManifest.xml b/quickstep/AndroidManifest.xml
index d3cec28..a06a2dd 100644
--- a/quickstep/AndroidManifest.xml
+++ b/quickstep/AndroidManifest.xml
@@ -47,10 +47,7 @@
</intent-filter>
</service>
- <!-- STOPSHIP: Change exported to false once all the integration is complete.
- It is set to true so that the activity can be started from command line -->
<activity android:name="com.android.quickstep.RecentsActivity"
- android:exported="true"
android:excludeFromRecents="true"
android:launchMode="singleTask"
android:clearTaskOnLaunch="true"
@@ -93,12 +90,12 @@
android:directBootAware="true" />
<activity
- android:name="com.android.quickstep.interaction.BackGestureTutorialActivity"
+ android:name="com.android.quickstep.interaction.GestureSandboxActivity"
android:autoRemoveFromRecents="true"
android:excludeFromRecents="true"
android:screenOrientation="portrait">
<intent-filter>
- <action android:name="com.android.quickstep.action.BACK_GESTURE_TUTORIAL" />
+ <action android:name="com.android.quickstep.action.GESTURE_SANDBOX" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
diff --git a/quickstep/recents_ui_overrides/res/drawable/hotseat_edu_notification_icon.xml b/quickstep/recents_ui_overrides/res/drawable/hotseat_edu_notification_icon.xml
index fa3a0f8..4fda2a9 100644
--- a/quickstep/recents_ui_overrides/res/drawable/hotseat_edu_notification_icon.xml
+++ b/quickstep/recents_ui_overrides/res/drawable/hotseat_edu_notification_icon.xml
@@ -15,5 +15,5 @@
-->
<vector android:height="24dp" android:viewportHeight="24"
android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="@color/bottom_panel_background" android:pathData="M19 9l1.25-2.75L23 5l-2.75-1.25L19 1l-1.25 2.75L15 5l2.75 1.25L19 9zm-7.5.5L9 4 6.5 9.5 1 12l5.5 2.5L9 20l2.5-5.5L17 12l-5.5-2.5zM19 15l-1.25 2.75L15 19l2.75 1.25L19 23l1.25-2.75L23 19l-2.75-1.25L19 15z"/>
+ <path android:fillColor="?android:attr/colorAccent" android:pathData="M19 9l1.25-2.75L23 5l-2.75-1.25L19 1l-1.25 2.75L15 5l2.75 1.25L19 9zm-7.5.5L9 4 6.5 9.5 1 12l5.5 2.5L9 20l2.5-5.5L17 12l-5.5-2.5zM19 15l-1.25 2.75L15 19l2.75 1.25L19 23l1.25-2.75L23 19l-2.75-1.25L19 15z"/>
</vector>
diff --git a/quickstep/recents_ui_overrides/res/layout/predicted_hotseat_edu.xml b/quickstep/recents_ui_overrides/res/layout/predicted_hotseat_edu.xml
index d94c665..fe99037 100644
--- a/quickstep/recents_ui_overrides/res/layout/predicted_hotseat_edu.xml
+++ b/quickstep/recents_ui_overrides/res/layout/predicted_hotseat_edu.xml
@@ -24,13 +24,13 @@
<View
android:layout_width="match_parent"
android:layout_height="32dp"
- android:backgroundTint="@color/bottom_panel_background"
+ android:backgroundTint="?android:attr/colorAccent"
android:background="@drawable/bottom_sheet_top_border" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:background="@color/bottom_panel_background"
+ android:background="?android:attr/colorAccent"
android:orientation="vertical">
<TextView
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduController.java
index bfbd00e..e7290a4 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduController.java
@@ -34,6 +34,7 @@
import com.android.launcher3.WorkspaceItemInfo;
import com.android.launcher3.uioverrides.QuickstepLauncher;
import com.android.launcher3.util.ActivityTracker;
+import com.android.launcher3.util.Themes;
import java.util.List;
@@ -109,7 +110,7 @@
NOTIFICATION_CHANNEL_ID)
.setContentTitle(name)
.setOngoing(true)
- .setColor(mLauncher.getColor(R.color.bottom_panel_background))
+ .setColor(Themes.getColorAccent(mLauncher))
.setContentIntent(PendingIntent.getActivity(mLauncher, 0, intent,
PendingIntent.FLAG_CANCEL_CURRENT))
.setSmallIcon(R.drawable.hotseat_edu_notification_icon)
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduDialog.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduDialog.java
index 00e72b1..8926246 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduDialog.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduDialog.java
@@ -191,7 +191,7 @@
|| predictions.size() < mLauncher.getDeviceProfile().inv.numHotseatIcons) {
return;
}
- mLauncher.getDragLayer().addView(this);
+ attachToContainer();
logOnBoardingSeen();
animateOpen();
for (int i = 0; i < mLauncher.getDeviceProfile().inv.numHotseatIcons; i++) {
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java
index a1c8378..7895bac 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java
@@ -37,6 +37,7 @@
import android.graphics.Rect;
import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
import android.view.animation.Interpolator;
import com.android.launcher3.AbstractFloatingView;
@@ -47,6 +48,7 @@
import com.android.launcher3.Workspace;
import com.android.launcher3.allapps.DiscoveryBounce;
import com.android.launcher3.anim.AnimatorSetBuilder;
+import com.android.launcher3.compat.AccessibilityManagerCompat;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import com.android.quickstep.SysUINavigationMode;
@@ -143,6 +145,10 @@
public void onStateTransitionEnd(Launcher launcher) {
launcher.getRotationHelper().setCurrentStateRequest(REQUEST_ROTATE);
DiscoveryBounce.showForOverviewIfNeeded(launcher);
+ RecentsView recentsView = launcher.getOverviewPanel();
+ AccessibilityManagerCompat.sendCustomAccessibilityEvent(
+ recentsView.getPageAt(recentsView.getCurrentPage()),
+ AccessibilityEvent.TYPE_VIEW_FOCUSED, null);
}
@Override
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/FlingAndHoldTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/FlingAndHoldTouchController.java
index b80830a..519939e 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/FlingAndHoldTouchController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/FlingAndHoldTouchController.java
@@ -172,7 +172,7 @@
mMotionPauseDetector.setDisallowPause(!handlingOverviewAnim()
|| upDisplacement < mMotionPauseMinDisplacement
|| upDisplacement > mMotionPauseMaxDisplacement);
- mMotionPauseDetector.addPosition(displacement, event.getEventTime());
+ mMotionPauseDetector.addPosition(event);
return super.onDrag(displacement, event);
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
index 8628db0..799f1ad 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
@@ -317,7 +317,7 @@
// home screen elements will appear in the shelf on motion pause.
mMotionPauseDetector.setDisallowPause(mIsHomeScreenVisible
|| -displacement.y < mMotionPauseMinDisplacement);
- mMotionPauseDetector.addPosition(displacement.y, ev.getEventTime());
+ mMotionPauseDetector.addPosition(ev);
if (mIsHomeScreenVisible) {
// Cancel the shelf anim so it doesn't clobber mNonOverviewAnim.
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
index 3364b66..28e8fb6 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
@@ -28,6 +28,7 @@
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_TRACING_ENABLED;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.ACTIVITY_TYPE_ASSISTANT;
import android.annotation.TargetApi;
@@ -63,6 +64,8 @@
import com.android.launcher3.provider.RestoreDbTask;
import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.TestProtocol;
+import com.android.launcher3.tracing.nano.LauncherTraceProto;
+import com.android.launcher3.tracing.nano.TouchInteractionServiceProto;
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
import com.android.launcher3.util.TraceHelper;
import com.android.quickstep.inputconsumers.AccessibilityInputConsumer;
@@ -76,6 +79,7 @@
import com.android.quickstep.inputconsumers.ScreenPinnedInputConsumer;
import com.android.quickstep.util.ActiveGestureLog;
import com.android.quickstep.util.AssistantUtilities;
+import com.android.quickstep.util.ProtoTracer;
import com.android.systemui.plugins.OverscrollPlugin;
import com.android.systemui.plugins.PluginListener;
import com.android.systemui.shared.recents.IOverviewProxy;
@@ -85,6 +89,7 @@
import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.shared.system.InputMonitorCompat;
import com.android.systemui.shared.system.RecentsAnimationListener;
+import com.android.systemui.shared.tracing.ProtoTraceable;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -113,7 +118,8 @@
* Service connected by system-UI for handling touch interaction.
*/
@TargetApi(Build.VERSION_CODES.Q)
-public class TouchInteractionService extends Service implements PluginListener<OverscrollPlugin> {
+public class TouchInteractionService extends Service implements PluginListener<OverscrollPlugin>,
+ ProtoTraceable<LauncherTraceProto> {
private static final String TAG = "TouchInteractionService";
@@ -275,6 +281,7 @@
mDeviceState = new RecentsAnimationDeviceState(this);
mDeviceState.addNavigationModeChangedCallback(this::onNavigationModeChanged);
mDeviceState.runOnUserUnlocked(this::onUserUnlocked);
+ ProtoTracer.INSTANCE.get(this).add(this);
sConnected = true;
}
@@ -381,6 +388,13 @@
SystemUiProxy.INSTANCE.get(this).setLastSystemUiStateFlags(
mDeviceState.getSystemUiStateFlags());
mOverviewComponentObserver.onSystemUiStateChanged();
+
+ // Update the tracing state
+ if ((mDeviceState.getSystemUiStateFlags() & SYSUI_STATE_TRACING_ENABLED) != 0) {
+ ProtoTracer.INSTANCE.get(TouchInteractionService.this).start();
+ } else {
+ ProtoTracer.INSTANCE.get(TouchInteractionService.this).stop();
+ }
}
}
@@ -403,6 +417,8 @@
disposeEventHandlers();
mDeviceState.destroy();
SystemUiProxy.INSTANCE.get(this).setProxy(null);
+ ProtoTracer.INSTANCE.get(TouchInteractionService.this).stop();
+ ProtoTracer.INSTANCE.get(this).remove(this);
sConnected = false;
super.onDestroy();
@@ -723,6 +739,9 @@
pw.println(" resumed=" + resumed);
pw.println(" mConsumer=" + mConsumer.getName());
ActiveGestureLog.INSTANCE.dump("", pw);
+ pw.println("ProtoTrace:");
+ pw.println(" file="
+ + ProtoTracer.INSTANCE.get(TouchInteractionService.this).getTraceFile());
}
}
@@ -753,7 +772,7 @@
protected boolean shouldNotifyBackGesture() {
return mBackGestureNotificationCounter > 0 &&
- mDeviceState.getGestureBlockedActivityPackage() != null;
+ !mDeviceState.getGestureBlockedActivityPackages().isEmpty();
}
@WorkerThread
@@ -762,8 +781,8 @@
mBackGestureNotificationCounter--;
Utilities.getDevicePrefs(this).edit()
.putInt(KEY_BACK_NOTIFICATION_COUNT, mBackGestureNotificationCounter).apply();
- sendBroadcast(new Intent(NOTIFY_ACTION_BACK).setPackage(
- mDeviceState.getGestureBlockedActivityPackage()));
+ mDeviceState.getGestureBlockedActivityPackages().forEach(blockedPackage ->
+ sendBroadcast(new Intent(NOTIFY_ACTION_BACK).setPackage(blockedPackage)));
}
}
@@ -781,4 +800,13 @@
public void onPluginDisconnected(OverscrollPlugin overscrollPlugin) {
mOverscrollPlugin = null;
}
+
+ @Override
+ public void writeToProto(LauncherTraceProto proto) {
+ if (proto.touchInteractionService == null) {
+ proto.touchInteractionService = new TouchInteractionServiceProto();
+ }
+ proto.touchInteractionService.serviceConnected = true;
+ proto.touchInteractionService.serviceConnected = true;
+ }
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/AccessibilityInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/AccessibilityInputConsumer.java
index d3765c5..5ad48eb 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/AccessibilityInputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/AccessibilityInputConsumer.java
@@ -31,8 +31,8 @@
import com.android.launcher3.R;
import com.android.quickstep.InputConsumer;
import com.android.quickstep.RecentsAnimationDeviceState;
-import com.android.quickstep.util.MotionPauseDetector;
import com.android.quickstep.SystemUiProxy;
+import com.android.quickstep.util.MotionPauseDetector;
import com.android.systemui.shared.system.InputMonitorCompat;
/**
@@ -117,9 +117,7 @@
if (pointerIndex == -1) {
break;
}
-
- mMotionPauseDetector.addPosition(ev.getY(pointerIndex) - mDownY,
- ev.getEventTime());
+ mMotionPauseDetector.addPosition(ev, pointerIndex);
}
break;
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
index 3ee3c2d..8e7074d 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
@@ -59,6 +59,7 @@
import com.android.quickstep.util.ActiveGestureLog;
import com.android.quickstep.util.CachedEventDispatcher;
import com.android.quickstep.util.MotionPauseDetector;
+import com.android.quickstep.util.NavBarPosition;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.InputMonitorCompat;
@@ -77,6 +78,7 @@
public static final float QUICKSTEP_TOUCH_SLOP_RATIO = 3;
private final RecentsAnimationDeviceState mDeviceState;
+ private final NavBarPosition mNavBarPosition;
private final TaskAnimationManager mTaskAnimationManager;
private final GestureState mGestureState;
private RecentsAnimationCallbacks mActiveCallbacks;
@@ -126,13 +128,16 @@
Factory handlerFactory) {
super(base);
mDeviceState = deviceState;
+ mNavBarPosition = mDeviceState.getNavBarPosition();
mTaskAnimationManager = taskAnimationManager;
mGestureState = gestureState;
mMainThreadHandler = new Handler(Looper.getMainLooper());
mHandlerFactory = handlerFactory;
mActivityInterface = mGestureState.getActivityInterface();
- mMotionPauseDetector = new MotionPauseDetector(base);
+ mMotionPauseDetector = new MotionPauseDetector(base, false,
+ mNavBarPosition.isLeftEdge() || mNavBarPosition.isRightEdge()
+ ? MotionEvent.AXIS_X : MotionEvent.AXIS_Y);
mMotionPauseMinDisplacement = base.getResources().getDimension(
R.dimen.motion_pause_detector_min_displacement_from_app);
mOnCompleteCallback = onCompleteCallback;
@@ -172,7 +177,7 @@
if (mPassedWindowMoveSlop && mInteractionHandler != null
&& !mRecentsViewDispatcher.hasConsumer()) {
mRecentsViewDispatcher.setConsumer(mInteractionHandler.getRecentsViewDispatcher(
- mDeviceState.getNavBarPosition().getRotationMode()));
+ mNavBarPosition.getRotationMode()));
}
int edgeFlags = ev.getEdgeFlags();
ev.setEdgeFlags(edgeFlags | EDGE_NAV_BAR);
@@ -285,7 +290,7 @@
if (mDeviceState.isFullyGesturalNavMode()) {
mMotionPauseDetector.setDisallowPause(upDist < mMotionPauseMinDisplacement
|| isLikelyToStartNewTask);
- mMotionPauseDetector.addPosition(displacement, ev.getEventTime());
+ mMotionPauseDetector.addPosition(ev);
mInteractionHandler.setIsLikelyToStartNewTask(isLikelyToStartNewTask);
}
}
@@ -354,9 +359,9 @@
ViewConfiguration.get(this).getScaledMaximumFlingVelocity());
float velocityX = mVelocityTracker.getXVelocity(mActivePointerId);
float velocityY = mVelocityTracker.getYVelocity(mActivePointerId);
- float velocity = mDeviceState.getNavBarPosition().isRightEdge()
+ float velocity = mNavBarPosition.isRightEdge()
? velocityX
- : mDeviceState.getNavBarPosition().isLeftEdge()
+ : mNavBarPosition.isLeftEdge()
? -velocityX
: velocityY;
@@ -410,9 +415,9 @@
}
private float getDisplacement(MotionEvent ev) {
- if (mDeviceState.getNavBarPosition().isRightEdge()) {
+ if (mNavBarPosition.isRightEdge()) {
return ev.getX() - mDownPos.x;
- } else if (mDeviceState.getNavBarPosition().isLeftEdge()) {
+ } else if (mNavBarPosition.isLeftEdge()) {
return mDownPos.x - ev.getX();
} else {
return ev.getY() - mDownPos.y;
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/ScreenPinnedInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/ScreenPinnedInputConsumer.java
index d5ed321..b9827ff 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/ScreenPinnedInputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/ScreenPinnedInputConsumer.java
@@ -23,8 +23,8 @@
import com.android.launcher3.R;
import com.android.quickstep.GestureState;
import com.android.quickstep.InputConsumer;
-import com.android.quickstep.util.MotionPauseDetector;
import com.android.quickstep.SystemUiProxy;
+import com.android.quickstep.util.MotionPauseDetector;
/**
* An input consumer that detects swipe up and hold to exit screen pinning mode.
@@ -72,7 +72,7 @@
case MotionEvent.ACTION_MOVE:
float displacement = mTouchDownY - y;
mMotionPauseDetector.setDisallowPause(displacement < mMotionPauseMinDisplacement);
- mMotionPauseDetector.addPosition(y, ev.getEventTime());
+ mMotionPauseDetector.addPosition(ev);
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ProtoTracer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ProtoTracer.java
new file mode 100644
index 0000000..190763a
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ProtoTracer.java
@@ -0,0 +1,127 @@
+/*
+ * 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.util;
+
+import static com.android.launcher3.tracing.nano.LauncherTraceFileProto.MagicNumber.MAGIC_NUMBER_H;
+import static com.android.launcher3.tracing.nano.LauncherTraceFileProto.MagicNumber.MAGIC_NUMBER_L;
+
+import android.content.Context;
+import android.os.SystemClock;
+
+import com.android.launcher3.tracing.nano.LauncherTraceProto;
+import com.android.launcher3.tracing.nano.LauncherTraceEntryProto;
+import com.android.launcher3.tracing.nano.LauncherTraceFileProto;
+import com.android.launcher3.util.MainThreadInitializedObject;
+import com.android.systemui.shared.tracing.FrameProtoTracer;
+import com.android.systemui.shared.tracing.FrameProtoTracer.ProtoTraceParams;
+import com.android.systemui.shared.tracing.ProtoTraceable;
+import com.google.protobuf.nano.MessageNano;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Queue;
+
+
+/**
+ * Controller for coordinating winscope proto tracing.
+ */
+public class ProtoTracer implements ProtoTraceParams<MessageNano,
+ LauncherTraceFileProto, LauncherTraceEntryProto, LauncherTraceProto> {
+
+ public static final MainThreadInitializedObject<ProtoTracer> INSTANCE =
+ new MainThreadInitializedObject<>(ProtoTracer::new);
+
+ private static final String TAG = "ProtoTracer";
+ private static final long MAGIC_NUMBER_VALUE = ((long) MAGIC_NUMBER_H << 32) | MAGIC_NUMBER_L;
+
+ private final Context mContext;
+ private final FrameProtoTracer<MessageNano,
+ LauncherTraceFileProto, LauncherTraceEntryProto, LauncherTraceProto> mProtoTracer;
+
+ public ProtoTracer(Context context) {
+ mContext = context;
+ mProtoTracer = new FrameProtoTracer<>(this);
+ }
+
+ @Override
+ public File getTraceFile() {
+ return new File(mContext.getFilesDir(), "launcher_trace.pb");
+ }
+
+ @Override
+ public LauncherTraceFileProto getEncapsulatingTraceProto() {
+ return new LauncherTraceFileProto();
+ }
+
+ @Override
+ public LauncherTraceEntryProto updateBufferProto(LauncherTraceEntryProto reuseObj,
+ ArrayList<ProtoTraceable<LauncherTraceProto>> traceables) {
+ LauncherTraceEntryProto proto = reuseObj != null
+ ? reuseObj
+ : new LauncherTraceEntryProto();
+ proto.elapsedRealtimeNanos = SystemClock.elapsedRealtimeNanos();
+ proto.launcher = proto.launcher != null ? proto.launcher : new LauncherTraceProto();
+ for (ProtoTraceable t : traceables) {
+ t.writeToProto(proto.launcher);
+ }
+ return proto;
+ }
+
+ @Override
+ public byte[] serializeEncapsulatingProto(LauncherTraceFileProto encapsulatingProto,
+ Queue<LauncherTraceEntryProto> buffer) {
+ encapsulatingProto.magicNumber = MAGIC_NUMBER_VALUE;
+ encapsulatingProto.entry = buffer.toArray(new LauncherTraceEntryProto[0]);
+ return MessageNano.toByteArray(encapsulatingProto);
+ }
+
+ @Override
+ public byte[] getProtoBytes(MessageNano proto) {
+ return MessageNano.toByteArray(proto);
+ }
+
+ @Override
+ public int getProtoSize(MessageNano proto) {
+ return proto.getCachedSize();
+ }
+
+ public void start() {
+ mProtoTracer.start();
+ }
+
+ public void stop() {
+ mProtoTracer.stop();
+ }
+
+ public void add(ProtoTraceable<LauncherTraceProto> traceable) {
+ mProtoTracer.add(traceable);
+ }
+
+ public void remove(ProtoTraceable<LauncherTraceProto> traceable) {
+ mProtoTracer.remove(traceable);
+ }
+
+ public void scheduleFrameUpdate() {
+ mProtoTracer.scheduleFrameUpdate();
+ }
+
+ public void update() {
+ mProtoTracer.update();
+ }
+}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
index ef1698e..fe78a84 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
@@ -92,6 +92,7 @@
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.PropertyListBuilder;
import com.android.launcher3.anim.SpringObjectAnimator;
+import com.android.launcher3.compat.AccessibilityManagerCompat;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.graphics.RotationMode;
import com.android.launcher3.userevent.nano.LauncherLogProto;
@@ -972,6 +973,10 @@
TaskView runningTask = getRunningTaskView();
if (runningTask != null) {
runningTask.setStableAlpha(isHidden ? 0 : mContentAlpha);
+ if (!isHidden) {
+ AccessibilityManagerCompat.sendCustomAccessibilityEvent(runningTask,
+ AccessibilityEvent.TYPE_VIEW_FOCUSED, null);
+ }
}
}
diff --git a/quickstep/res/values/config.xml b/quickstep/res/values/config.xml
index 327bb14..a688f9a 100644
--- a/quickstep/res/values/config.xml
+++ b/quickstep/res/values/config.xml
@@ -13,11 +13,13 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<resources>
- <string name="task_overlay_factory_class" translatable="false"></string>
+<resources xmlns:tools="http://schemas.android.com/tools">
+ <string name="task_overlay_factory_class" translatable="false"/>
- <!-- Activity which blocks home gesture -->
- <string name="gesture_blocking_activity" translatable="false"></string>
+ <!-- Activities which block home gesture -->
+ <string-array name="gesture_blocking_activities" tools:ignore="InconsistentArrays">
+ <item>com.android.launcher3/com.android.quickstep.interaction.GestureSandboxActivity</item>
+ </string-array>
<string name="stats_log_manager_class" translatable="false">com.android.quickstep.logging.StatsLogCompatManager</string>
@@ -32,5 +34,5 @@
<integer name="assistant_gesture_min_time_threshold">200</integer>
<integer name="assistant_gesture_corner_deg_threshold">20</integer>
- <string name="wellbeing_provider_pkg" translatable="false"></string>
+ <string name="wellbeing_provider_pkg" translatable="false"/>
</resources>
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java b/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
index e88a8a4..b5e05ee 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
@@ -54,6 +54,12 @@
}
@Override
+ public void onStateDisabled(Launcher launcher) {
+ super.onStateDisabled(launcher);
+ AbstractFloatingView.closeAllOpenViews(launcher);
+ }
+
+ @Override
public String getDescription(Launcher launcher) {
AllAppsContainerView appsView = launcher.getAppsView();
return appsView.getDescription();
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
index 4b33d21..abe1592 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
@@ -66,6 +66,8 @@
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
/**
* Manages the state of the system during a swipe up gesture.
@@ -107,7 +109,7 @@
private Region mExclusionRegion;
private SystemGestureExclusionListenerCompat mExclusionListener;
- private ComponentName mGestureBlockedActivity;
+ private final List<ComponentName> mGestureBlockedActivities;
public RecentsAnimationDeviceState(Context context) {
final ContentResolver resolver = context.getContentResolver();
@@ -142,9 +144,19 @@
runOnDestroy(() -> mSysUiNavMode.removeModeChangeListener(this));
// Add any blocked activities
- String blockingActivity = context.getString(R.string.gesture_blocking_activity);
- if (!TextUtils.isEmpty(blockingActivity)) {
- mGestureBlockedActivity = ComponentName.unflattenFromString(blockingActivity);
+ String[] blockingActivities;
+ try {
+ blockingActivities =
+ context.getResources().getStringArray(R.array.gesture_blocking_activities);
+ } catch (Resources.NotFoundException e) {
+ blockingActivities = new String[0];
+ }
+ mGestureBlockedActivities = new ArrayList<>(blockingActivities.length);
+ for (String blockingActivity : blockingActivities) {
+ if (!TextUtils.isEmpty(blockingActivity)) {
+ mGestureBlockedActivities.add(
+ ComponentName.unflattenFromString(blockingActivity));
+ }
}
}
@@ -272,17 +284,16 @@
* @return whether the given running task info matches the gesture-blocked activity.
*/
public boolean isGestureBlockedActivity(ActivityManager.RunningTaskInfo runningTaskInfo) {
- return runningTaskInfo != null && mGestureBlockedActivity != null
- && mGestureBlockedActivity.equals(runningTaskInfo.topActivity);
+ return runningTaskInfo != null
+ && mGestureBlockedActivities.contains(runningTaskInfo.topActivity);
}
/**
- * @return the package of the gesture-blocked activity or {@code null} if there is none.
+ * @return the packages of gesture-blocked activities.
*/
- public String getGestureBlockedActivityPackage() {
- return (mGestureBlockedActivity != null)
- ? mGestureBlockedActivity.getPackageName()
- : null;
+ public List<String> getGestureBlockedActivityPackages() {
+ return mGestureBlockedActivities.stream().map(ComponentName::getPackageName)
+ .collect(Collectors.toList());
}
/**
diff --git a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialActivity.java b/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java
similarity index 76%
rename from quickstep/src/com/android/quickstep/interaction/BackGestureTutorialActivity.java
rename to quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java
index 295ab48..8081ad7 100644
--- a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialActivity.java
+++ b/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java
@@ -16,7 +16,10 @@
package com.android.quickstep.interaction;
import android.graphics.Color;
+import android.graphics.Rect;
import android.os.Bundle;
+import android.util.DisplayMetrics;
+import android.view.Display;
import android.view.View;
import android.view.Window;
@@ -26,10 +29,11 @@
import com.android.quickstep.interaction.BackGestureTutorialFragment.TutorialStep;
import com.android.quickstep.interaction.BackGestureTutorialFragment.TutorialType;
+import java.util.List;
import java.util.Optional;
-/** Shows the Back gesture interactive tutorial in full screen mode. */
-public class BackGestureTutorialActivity extends FragmentActivity {
+/** Shows the gesture interactive sandbox in full screen mode. */
+public class GestureSandboxActivity extends FragmentActivity {
Optional<BackGestureTutorialFragment> mFragment = Optional.empty();
@@ -47,6 +51,12 @@
}
@Override
+ public void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ disableSystemGestures();
+ }
+
+ @Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
@@ -70,4 +80,14 @@
| View.SYSTEM_UI_FLAG_FULLSCREEN);
getWindow().setNavigationBarColor(Color.TRANSPARENT);
}
+
+ private void disableSystemGestures() {
+ Display display = getDisplay();
+ if (display != null) {
+ DisplayMetrics metrics = new DisplayMetrics();
+ display.getMetrics(metrics);
+ getWindow().setSystemGestureExclusionRects(
+ List.of(new Rect(0, 0, metrics.widthPixels, metrics.heightPixels)));
+ }
+ }
}
diff --git a/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java b/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
index 801a560..d8b10b6 100644
--- a/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
+++ b/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
@@ -37,8 +37,7 @@
private static final long FORCE_PAUSE_TIMEOUT = 300;
/**
- * After {@link #makePauseHarderToTrigger()}, must
- * move slowly for this long to trigger a pause.
+ * After {@link #mMakePauseHarderToTrigger}, must move slowly for this long to trigger a pause.
*/
private static final long HARDER_TRIGGER_TIMEOUT = 400;
@@ -49,13 +48,10 @@
private final Alarm mForcePauseTimeout;
private final boolean mMakePauseHarderToTrigger;
private final Context mContext;
+ private final VelocityProvider mVelocityProvider;
- private Long mPreviousTime = null;
- private Float mPreviousPosition = null;
private Float mPreviousVelocity = null;
- private Float mFirstPosition = null;
-
private OnMotionPauseListener mOnMotionPauseListener;
private boolean mIsPaused;
// Bias more for the first pause to make it feel extra responsive.
@@ -73,6 +69,13 @@
* @param makePauseHarderToTrigger Used for gestures that require a more explicit pause.
*/
public MotionPauseDetector(Context context, boolean makePauseHarderToTrigger) {
+ this(context, makePauseHarderToTrigger, MotionEvent.AXIS_Y);
+ }
+
+ /**
+ * @param makePauseHarderToTrigger Used for gestures that require a more explicit pause.
+ */
+ public MotionPauseDetector(Context context, boolean makePauseHarderToTrigger, int axis) {
mContext = context;
Resources res = context.getResources();
mSpeedVerySlow = res.getDimension(R.dimen.motion_pause_detector_speed_very_slow);
@@ -82,6 +85,7 @@
mForcePauseTimeout = new Alarm();
mForcePauseTimeout.setOnAlarmListener(alarm -> updatePaused(true /* isPaused */));
mMakePauseHarderToTrigger = makePauseHarderToTrigger;
+ mVelocityProvider = new LinearVelocityProvider(axis);
}
/**
@@ -101,28 +105,28 @@
/**
* Computes velocity and acceleration to determine whether the motion is paused.
- * @param position The x or y component of the motion being tracked.
+ * @param ev The motion being tracked.
*
* TODO: Use historical positions as well, e.g. {@link MotionEvent#getHistoricalY(int, int)}.
*/
- public void addPosition(float position, long time) {
- if (mFirstPosition == null) {
- mFirstPosition = position;
- }
+ public void addPosition(MotionEvent ev) {
+ addPosition(ev, 0);
+ }
+
+ /**
+ * Computes velocity and acceleration to determine whether the motion is paused.
+ * @param ev The motion being tracked.
+ * @param pointerIndex Index for the pointer being tracked in the motion event
+ */
+ public void addPosition(MotionEvent ev, int pointerIndex) {
mForcePauseTimeout.setAlarm(mMakePauseHarderToTrigger
? HARDER_TRIGGER_TIMEOUT
: FORCE_PAUSE_TIMEOUT);
- if (mPreviousTime != null && mPreviousPosition != null) {
- long changeInTime = Math.max(1, time - mPreviousTime);
- float changeInPosition = position - mPreviousPosition;
- float velocity = changeInPosition / changeInTime;
- if (mPreviousVelocity != null) {
- checkMotionPaused(velocity, mPreviousVelocity, time);
- }
- mPreviousVelocity = velocity;
+ Float newVelocity = mVelocityProvider.addMotionEvent(ev, pointerIndex);
+ if (newVelocity != null && mPreviousVelocity != null) {
+ checkMotionPaused(newVelocity, mPreviousVelocity, ev.getEventTime());
}
- mPreviousTime = time;
- mPreviousPosition = position;
+ mPreviousVelocity = newVelocity;
}
private void checkMotionPaused(float velocity, float prevVelocity, long time) {
@@ -178,10 +182,8 @@
}
public void clear() {
- mPreviousTime = null;
- mPreviousPosition = null;
+ mVelocityProvider.clear();
mPreviousVelocity = null;
- mFirstPosition = null;
setOnMotionPauseListener(null);
mIsPaused = mHasEverBeenPaused = false;
mSlowStartTime = 0;
@@ -195,4 +197,55 @@
public interface OnMotionPauseListener {
void onMotionPauseChanged(boolean isPaused);
}
+
+ /**
+ * Interface to abstract out velocity calculations
+ */
+ protected interface VelocityProvider {
+
+ /**
+ * Adds a new motion events, and returns the velocity at this point, or null if
+ * the velocity is not available
+ */
+ Float addMotionEvent(MotionEvent ev, int pointer);
+
+ /**
+ * Clears all stored motion event records
+ */
+ void clear();
+ }
+
+ private static class LinearVelocityProvider implements VelocityProvider {
+
+ private Long mPreviousTime = null;
+ private Float mPreviousPosition = null;
+
+ private final int mAxis;
+
+ LinearVelocityProvider(int axis) {
+ mAxis = axis;
+ }
+
+ @Override
+ public Float addMotionEvent(MotionEvent ev, int pointer) {
+ long time = ev.getEventTime();
+ float position = ev.getAxisValue(mAxis, pointer);
+ Float velocity = null;
+
+ if (mPreviousTime != null && mPreviousPosition != null) {
+ long changeInTime = Math.max(1, time - mPreviousTime);
+ float changeInPosition = position - mPreviousPosition;
+ velocity = changeInPosition / changeInTime;
+ }
+ mPreviousTime = time;
+ mPreviousPosition = position;
+ return velocity;
+ }
+
+ @Override
+ public void clear() {
+ mPreviousTime = null;
+ mPreviousPosition = null;
+ }
+ }
}
diff --git a/res/layout/work_apps_paused.xml b/res/layout/work_apps_paused.xml
index 33502d0..1c18076 100644
--- a/res/layout/work_apps_paused.xml
+++ b/res/layout/work_apps_paused.xml
@@ -15,9 +15,9 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:background="?attr/allAppsScrimColor"
android:padding="8dp"
android:orientation="vertical"
- android:background="?attr/allAppsScrimColor"
android:gravity="center">
<ImageView
@@ -38,7 +38,7 @@
android:layout_marginBottom="8dp"
android:text="@string/work_apps_paused_title"
android:textAlignment="center"
- android:textSize="24sp" />
+ android:textSize="20sp" />
<TextView
android:layout_width="wrap_content"
diff --git a/res/layout/work_profile_edu.xml b/res/layout/work_profile_edu.xml
index f7a529d..04094c4 100644
--- a/res/layout/work_profile_edu.xml
+++ b/res/layout/work_profile_edu.xml
@@ -21,22 +21,22 @@
<View
android:layout_width="match_parent"
- android:backgroundTint="@color/bottom_panel_background"
android:layout_height="32dp"
- android:background="@drawable/bottom_sheet_top_border" />
+ android:background="@drawable/bottom_sheet_top_border"
+ android:backgroundTint="?android:attr/colorAccent" />
<LinearLayout
android:id="@+id/view_wrapper"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:background="@color/bottom_panel_background"
+ android:background="?android:attr/colorAccent"
android:orientation="vertical"
android:paddingLeft="@dimen/bottom_sheet_edu_padding"
android:paddingRight="@dimen/bottom_sheet_edu_padding">
<TextView
- style="@style/TextHeadline"
android:id="@+id/content_text"
+ style="@style/TextHeadline"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="48dp"
@@ -57,5 +57,4 @@
android:textAlignment="center"
android:textColor="@android:color/white" />
</LinearLayout>
-
</com.android.launcher3.views.WorkEduView>
\ No newline at end of file
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 36f8468..194ef2c 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -45,5 +45,4 @@
<color name="back_gesture_tutorial_primary_color">#1A73E8</color> <!-- Blue -->
- <color name="bottom_panel_background">#f01A73E8</color>
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index bde3c31..9d0fb56 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -142,7 +142,7 @@
<string name="uninstall_system_app_text">This is a system app and can\'t be uninstalled.</string>
<!-- Default folder title -->
- <string name="folder_hint_text">Tap to edit</string>
+ <string name="folder_hint_text">Edit Name</string>
<!-- Accessibility -->
<!-- The format string for when an app is temporarily disabled. -->
@@ -330,7 +330,7 @@
<!--- User onboarding title for personal apps -->
<string name="work_profile_edu_personal_apps">Personal apps are private & can\'t be seen by IT</string>
<!--- User onboarding title for work profile apps -->
- <string name="work_profile_edu_work_apps">Work apps are badged and monitored by IT</string>
+ <string name="work_profile_edu_work_apps">Work apps are badged & visible to IT</string>
<!-- Action label to proceed to the next work profile edu section-->
<string name="work_profile_edu_next">Next</string>
<!-- Action label to finish work profile edu-->
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 3a275ff..3fc8de2 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -482,7 +482,6 @@
@Override
public void onEnterAnimationComplete() {
super.onEnterAnimationComplete();
- mAllAppsController.highlightWorkTabIfNecessary();
mRotationHelper.setCurrentTransitionRequest(REQUEST_NONE);
}
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index ac0fef8..f618fe1 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -66,7 +66,6 @@
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
-import java.util.Optional;
import java.util.concurrent.CancellationException;
import java.util.concurrent.Executor;
import java.util.function.Supplier;
@@ -127,16 +126,6 @@
}
/**
- * Returns AppInfo with corresponding package name.
- * TODO: move to enqueueModelTask
- */
- public Optional<AppInfo> getAppInfoByPackageName(String pkg) {
- return mBgAllAppsList.data.stream()
- .filter(info -> info.componentName.getPackageName().equals(pkg))
- .findAny();
- }
-
- /**
* Adds the provided items to the workspace.
*/
public void addAndBindAddedWorkspaceItems(List<Pair<ItemInfo, Object>> itemList) {
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index 4c6e1f3..01893e9 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -374,6 +374,8 @@
protected void onPageEndTransition() {
mWasInOverscroll = false;
AccessibilityManagerCompat.sendScrollFinishedEventToTest(getContext());
+ AccessibilityManagerCompat.sendCustomAccessibilityEvent(getPageAt(mCurrentPage),
+ AccessibilityEvent.TYPE_VIEW_FOCUSED, null);
}
protected int getUnboundedScrollX() {
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index 4e5b031..fcccc59 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -103,6 +103,8 @@
private final MultiValueAlpha mMultiValueAlpha;
+ Rect mInsets = new Rect();
+
public AllAppsContainerView(Context context) {
this(context, null);
}
@@ -325,6 +327,7 @@
@Override
public void setInsets(Rect insets) {
+ mInsets.set(insets);
DeviceProfile grid = mLauncher.getDeviceProfile();
int leftRightPadding = grid.desiredWorkspaceLeftRightMarginPx
+ grid.cellLayoutPaddingLeftRightPx;
@@ -416,6 +419,7 @@
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
this.addView(mWorkFooterContainer);
+ mWorkFooterContainer.setInsets(mInsets);
mWorkFooterContainer.post(() -> mAH[AdapterHolder.WORK].applyPadding());
}
@@ -553,17 +557,6 @@
return mHeader != null && mHeader.getVisibility() == View.VISIBLE;
}
- public void onScrollUpEnd() {
- highlightWorkTabIfNecessary();
- }
-
- void highlightWorkTabIfNecessary() {
- if (mUsingTabs) {
- ((PersonalWorkSlidingTabStrip) findViewById(R.id.tabs))
- .highlightWorkTabIfNecessary();
- }
- }
-
/**
* Adds an update listener to {@param animator} that adds springs to the animation.
*/
@@ -648,9 +641,9 @@
R.layout.work_apps_paused, null);
recyclerView.post(() -> {
int width = recyclerView.getWidth();
- int height = recyclerView.getHeight();
- pausedOverlay.measure(makeMeasureSpec(width, EXACTLY),
- makeMeasureSpec(height, EXACTLY));
+ int height = recyclerView.getHeight() - mWorkFooterContainer.getHeight();
+ pausedOverlay.measure(makeMeasureSpec(recyclerView.getWidth(), EXACTLY),
+ makeMeasureSpec(recyclerView.getHeight(), EXACTLY));
pausedOverlay.layout(0, 0, width, height);
applyPadding();
});
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index 93bdac9..6aa3efc 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -248,18 +248,6 @@
private void onProgressAnimationEnd() {
if (Float.compare(mProgress, 1f) == 0) {
mAppsView.reset(false /* animate */);
- } else if (isAllAppsExpanded()) {
- mAppsView.onScrollUpEnd();
- }
- }
-
- private boolean isAllAppsExpanded() {
- return Float.compare(mProgress, 0f) == 0;
- }
-
- public void highlightWorkTabIfNecessary() {
- if (isAllAppsExpanded()) {
- mAppsView.highlightWorkTabIfNecessary();
}
}
}
diff --git a/src/com/android/launcher3/allapps/DiscoveryBounce.java b/src/com/android/launcher3/allapps/DiscoveryBounce.java
index e8035eb..0f0fc3a 100644
--- a/src/com/android/launcher3/allapps/DiscoveryBounce.java
+++ b/src/com/android/launcher3/allapps/DiscoveryBounce.java
@@ -35,7 +35,6 @@
import com.android.launcher3.LauncherStateManager.StateListener;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
-import com.android.launcher3.pm.UserCache;
/**
* Abstract base class of floating view responsible for showing discovery bounce animation
@@ -144,8 +143,7 @@
private static void showForHomeIfNeeded(Launcher launcher, boolean withDelay) {
if (!launcher.isInState(NORMAL)
- || (launcher.getSharedPrefs().getBoolean(HOME_BOUNCE_SEEN, false)
- && !shouldShowForWorkProfile(launcher))
+ || launcher.getSharedPrefs().getBoolean(HOME_BOUNCE_SEEN, false)
|| AbstractFloatingView.getTopOpenView(launcher) != null
|| launcher.getSystemService(UserManager.class).isDemoUser()
|| Utilities.IS_RUNNING_IN_TEST_HARNESS) {
@@ -170,8 +168,7 @@
|| !launcher.hasBeenResumed()
|| launcher.isForceInvisible()
|| launcher.getDeviceProfile().isVerticalBarLayout()
- || (launcher.getSharedPrefs().getBoolean(SHELF_BOUNCE_SEEN, false)
- && !shouldShowForWorkProfile(launcher))
+ || launcher.getSharedPrefs().getBoolean(SHELF_BOUNCE_SEEN, false)
|| launcher.getSystemService(UserManager.class).isDemoUser()
|| Utilities.IS_RUNNING_IN_TEST_HARNESS) {
return;
@@ -213,12 +210,6 @@
}
}
- private static boolean shouldShowForWorkProfile(Launcher launcher) {
- return !launcher.getSharedPrefs().getBoolean(
- PersonalWorkSlidingTabStrip.KEY_SHOWED_PEEK_WORK_TAB, false)
- && UserCache.INSTANCE.get(launcher).hasWorkProfile();
- }
-
private static void incrementShelfBounceCount(Launcher launcher) {
SharedPreferences sharedPrefs = launcher.getSharedPrefs();
int count = sharedPrefs.getInt(SHELF_BOUNCE_COUNT, 0);
diff --git a/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java b/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java
index 9d0ecd3..25db0e7 100644
--- a/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java
@@ -64,6 +64,14 @@
}
@Override
+ public void setupHeader() {
+ super.setupHeader();
+ if (mWorkTabListener != null && !mUsingTabs) {
+ mLauncher.getStateManager().removeStateListener(mWorkTabListener);
+ }
+ }
+
+ @Override
public void onTabChanged(int pos) {
super.onTabChanged(pos);
if (mUsingTabs) {
diff --git a/src/com/android/launcher3/allapps/PersonalWorkSlidingTabStrip.java b/src/com/android/launcher3/allapps/PersonalWorkSlidingTabStrip.java
index 6204f31..0e39bbe 100644
--- a/src/com/android/launcher3/allapps/PersonalWorkSlidingTabStrip.java
+++ b/src/com/android/launcher3/allapps/PersonalWorkSlidingTabStrip.java
@@ -16,7 +16,6 @@
package com.android.launcher3.allapps;
import android.content.Context;
-import android.content.SharedPreferences;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
@@ -39,11 +38,8 @@
private static final int POSITION_PERSONAL = 0;
private static final int POSITION_WORK = 1;
- public static final String KEY_SHOWED_PEEK_WORK_TAB = "showed_peek_work_tab";
-
private final Paint mSelectedIndicatorPaint;
private final Paint mDividerPaint;
- private final SharedPreferences mSharedPreferences;
private int mSelectedIndicatorHeight;
private int mIndicatorLeft = -1;
@@ -72,7 +68,6 @@
mDividerPaint.setStrokeWidth(
getResources().getDimensionPixelSize(R.dimen.all_apps_divider_height));
- mSharedPreferences = Utilities.getPrefs(context);
mIsRtl = Utilities.isRtl(getResources());
}
@@ -128,25 +123,6 @@
mIndicatorRight, getHeight(), mSelectedIndicatorPaint);
}
- public void highlightWorkTabIfNecessary() {
- if (mSharedPreferences.getBoolean(KEY_SHOWED_PEEK_WORK_TAB, false)) {
- return;
- }
- if (mLastActivePage != POSITION_PERSONAL) {
- return;
- }
- highlightWorkTab();
- mSharedPreferences.edit().putBoolean(KEY_SHOWED_PEEK_WORK_TAB, true).apply();
- }
-
- private void highlightWorkTab() {
- View v = getChildAt(POSITION_WORK);
- v.post(() -> {
- v.setPressed(true);
- v.setPressed(false);
- });
- }
-
@Override
public void setScroll(int currentScroll, int totalScroll) {
float scrollOffset = ((float) currentScroll) / totalScroll;
diff --git a/src/com/android/launcher3/compat/AccessibilityManagerCompat.java b/src/com/android/launcher3/compat/AccessibilityManagerCompat.java
index 28579c1..db4bef0 100644
--- a/src/com/android/launcher3/compat/AccessibilityManagerCompat.java
+++ b/src/com/android/launcher3/compat/AccessibilityManagerCompat.java
@@ -18,11 +18,14 @@
import android.content.Context;
import android.os.Bundle;
+import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
+import androidx.annotation.Nullable;
+
import com.android.launcher3.Utilities;
import com.android.launcher3.testing.TestProtocol;
@@ -37,11 +40,13 @@
return isAccessibilityEnabled(context);
}
- public static void sendCustomAccessibilityEvent(View target, int type, String text) {
+ public static void sendCustomAccessibilityEvent(View target, int type, @Nullable String text) {
if (isObservedEventType(target.getContext(), type)) {
AccessibilityEvent event = AccessibilityEvent.obtain(type);
target.onInitializeAccessibilityEvent(event);
- event.getText().add(text);
+ if (!TextUtils.isEmpty(text)) {
+ event.getText().add(text);
+ }
getManager(target.getContext()).sendAccessibilityEvent(event);
}
}
diff --git a/src/com/android/launcher3/dragndrop/DragController.java b/src/com/android/launcher3/dragndrop/DragController.java
index 1b7b015..de7bc6d 100644
--- a/src/com/android/launcher3/dragndrop/DragController.java
+++ b/src/com/android/launcher3/dragndrop/DragController.java
@@ -160,8 +160,8 @@
mOptions = options;
if (mOptions.systemDndStartPoint != null) {
- mMotionDownX = mOptions.systemDndStartPoint.x;
- mMotionDownY = mOptions.systemDndStartPoint.y;
+ mLastTouch[0] = mMotionDownX = mOptions.systemDndStartPoint.x;
+ mLastTouch[1] = mMotionDownY = mOptions.systemDndStartPoint.y;
}
final int registrationX = mMotionDownX - dragLayerX;
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index 1b45f10..c72509e 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -326,7 +326,7 @@
(FolderNameInfo[]) mInfo.suggestedFolderNames.getParcelableArrayExtra(
FolderInfo.EXTRA_FOLDER_SUGGESTIONS);
if (nameInfos != null) {
- showLabelSuggestion(nameInfos);
+ showLabelSuggestion(nameInfos, false);
}
}
}
@@ -350,18 +350,11 @@
mFolderIcon.onTitleChanged(newTitle);
mLauncher.getModelWriter().updateItemInDatabase(mInfo);
- if (FeatureFlags.FOLDER_NAME_SUGGEST.get()) {
- mFolderName.setText(mInfo.title);
- // TODO: depending on whether the title was manually edited or automatically
- // suggested, apply different hint.
- mFolderName.setHint("");
+ if (TextUtils.isEmpty(mInfo.title)) {
+ mFolderName.setHint(R.string.folder_hint_text);
+ mFolderName.setText("");
} else {
- if (isEmpty(mInfo.title)) {
- mFolderName.setHint(R.string.folder_hint_text);
- mFolderName.setText("");
- } else {
- mFolderName.setHint(null);
- }
+ mFolderName.setHint(null);
}
sendCustomAccessibilityEvent(
@@ -475,7 +468,7 @@
nameInfos);
if (isEmpty(mFolderName.getText().toString())
&& !mInfo.hasOption(FLAG_MANUAL_FOLDER_NAME)) {
- showLabelSuggestion(nameInfos);
+ showLabelSuggestion(nameInfos, true);
}
}
}
@@ -484,7 +477,7 @@
* Show suggested folder title in FolderEditText if the first suggestion is non-empty, push
* InputMethodManager suggestions.
*/
- private void showLabelSuggestion(FolderNameInfo[] nameInfos) {
+ private void showLabelSuggestion(FolderNameInfo[] nameInfos, boolean animate) {
if (nameInfos == null) {
return;
}
@@ -494,15 +487,16 @@
nameInfos[0].getLabel())
|| nameInfos.length > 1 && nameInfos[1] != null && !isEmpty(
nameInfos[1].getLabel());
- CharSequence firstLabel = nameInfos[0].getLabel();
if (shouldOpen) {
+ CharSequence firstLabel = nameInfos[0] == null ? "" : nameInfos[0].getLabel();
if (!isEmpty(firstLabel)) {
mFolderName.setHint("");
mFolderName.setText(firstLabel);
- mInfo.title = firstLabel;
}
- animateOpen(mInfo.contents, 0, true);
+ if (animate) {
+ animateOpen(mInfo.contents, 0, true);
+ }
mFolderName.showKeyboard();
mFolderName.displayCompletions(
asList(nameInfos).subList(1, nameInfos.length).stream()
@@ -1658,6 +1652,7 @@
.getParcelableArrayExtra(FolderInfo.EXTRA_FOLDER_SUGGESTIONS))
.map(folderNameInfoArray ->
stream(folderNameInfoArray)
+ .filter(Objects::nonNull)
.map(FolderNameInfo::getLabel)
.map(CharSequence::toString)
.toArray(String[]::new));
diff --git a/src/com/android/launcher3/folder/FolderNameInfo.java b/src/com/android/launcher3/folder/FolderNameInfo.java
index eb9da90..ecbe46c 100644
--- a/src/com/android/launcher3/folder/FolderNameInfo.java
+++ b/src/com/android/launcher3/folder/FolderNameInfo.java
@@ -80,4 +80,10 @@
public int describeContents() {
return 0;
}
+
+ @Override
+ @NonNull
+ public String toString() {
+ return mLabel.toString() + ":" + mScore;
+ }
}
diff --git a/src/com/android/launcher3/folder/FolderNameProvider.java b/src/com/android/launcher3/folder/FolderNameProvider.java
index d5990fa..184dbb9 100644
--- a/src/com/android/launcher3/folder/FolderNameProvider.java
+++ b/src/com/android/launcher3/folder/FolderNameProvider.java
@@ -21,9 +21,14 @@
import android.util.Log;
import com.android.launcher3.AppInfo;
+import com.android.launcher3.FolderInfo;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.R;
import com.android.launcher3.WorkspaceItemInfo;
+import com.android.launcher3.model.AllAppsList;
+import com.android.launcher3.model.BaseModelUpdateTask;
+import com.android.launcher3.model.BgDataModel;
+import com.android.launcher3.util.IntSparseArrayMap;
import com.android.launcher3.util.ResourceBasedOverride;
import java.util.ArrayList;
@@ -50,6 +55,8 @@
* name edit box can also be used to provide suggestion.
*/
public static final int SUGGEST_MAX = 4;
+ protected IntSparseArrayMap<FolderInfo> mFolderInfos;
+ protected List<AppInfo> mAppInfos;
/**
* Retrieve instance of this object that can be overridden in runtime based on the build
@@ -58,9 +65,30 @@
public static FolderNameProvider newInstance(Context context) {
FolderNameProvider fnp = Overrides.getObject(FolderNameProvider.class,
context.getApplicationContext(), R.string.folder_name_provider_class);
+ fnp.load(context);
+
return fnp;
}
+ public static FolderNameProvider newInstance(Context context, List<AppInfo> appInfos,
+ IntSparseArrayMap<FolderInfo> folderInfos) {
+ FolderNameProvider fnp = Overrides.getObject(FolderNameProvider.class,
+ context.getApplicationContext(), R.string.folder_name_provider_class);
+ fnp.load(appInfos, folderInfos);
+
+ return fnp;
+ }
+
+ private void load(Context context) {
+ LauncherAppState.getInstance(context).getModel().enqueueModelUpdateTask(
+ new FolderNameWorker());
+ }
+
+ private void load(List<AppInfo> appInfos, IntSparseArrayMap<FolderInfo> folderInfos) {
+ mAppInfos = appInfos;
+ mFolderInfos = folderInfos;
+ }
+
/**
* Generate and rank the suggested Folder names.
*/
@@ -92,9 +120,8 @@
.collect(Collectors.toList());
if (distinctItemInfos.size() == 1) {
- Optional<AppInfo> info = LauncherAppState.getInstance(context).getModel()
- .getAppInfoByPackageName(distinctItemInfos.get(0).getTargetComponent()
- .getPackageName());
+ Optional<AppInfo> info = getAppInfoByPackageName(
+ distinctItemInfos.get(0).getTargetComponent().getPackageName());
// Place it as first viable suggestion and shift everything else
info.ifPresent(i -> setAsFirstSuggestion(nameInfos, i.title.toString()));
}
@@ -103,6 +130,15 @@
}
}
+ private Optional<AppInfo> getAppInfoByPackageName(String packageName) {
+ if (mAppInfos == null || mAppInfos.isEmpty()) {
+ return Optional.empty();
+ }
+ return mAppInfos.stream()
+ .filter(info -> info.componentName.getPackageName().equals(packageName))
+ .findAny();
+ }
+
private void setAsFirstSuggestion(FolderNameInfo[] nameInfos, CharSequence label) {
if (nameInfos.length == 0 || contains(nameInfos, label)) {
return;
@@ -143,4 +179,13 @@
Map<Object, Boolean> map = new ConcurrentHashMap<>();
return t -> map.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
}
+
+ private class FolderNameWorker extends BaseModelUpdateTask {
+ @Override
+ public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) {
+ mFolderInfos = dataModel.folders.clone();
+ mAppInfos = Arrays.asList(apps.copyData());
+ }
+ }
+
}
diff --git a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
index def76e8..a429af2 100644
--- a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
+++ b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
@@ -25,6 +25,7 @@
import android.annotation.TargetApi;
import android.app.Fragment;
+import android.appwidget.AppWidgetHostView;
import android.content.Context;
import android.content.Intent;
import android.content.res.TypedArray;
@@ -55,6 +56,7 @@
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherAppWidgetInfo;
import com.android.launcher3.LauncherModel;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.LauncherSettings.Favorites;
@@ -72,6 +74,8 @@
import com.android.launcher3.model.BgDataModel;
import com.android.launcher3.model.BgDataModel.Callbacks;
import com.android.launcher3.model.LoaderResults;
+import com.android.launcher3.model.WidgetItem;
+import com.android.launcher3.model.WidgetsModel;
import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.views.BaseDragLayer;
@@ -248,6 +252,16 @@
addInScreenFromBind(folderIcon, info);
}
+ private void inflateAndAddWidgets(LauncherAppWidgetInfo info, WidgetsModel widgetsModel) {
+ WidgetItem widgetItem = widgetsModel.getWidgetProviderInfoByProviderName(
+ info.providerName);
+ AppWidgetHostView view = new AppWidgetHostView(mContext);
+ view.setAppWidget(-1, widgetItem.widgetInfo);
+ view.updateAppWidget(null);
+ view.setTag(info);
+ addInScreenFromBind(view, info);
+ }
+
private void dispatchVisibilityAggregated(View view, boolean isVisible) {
// Similar to View.dispatchVisibilityAggregated implementation.
final boolean thisVisible = view.getVisibility() == VISIBLE;
@@ -272,9 +286,9 @@
mContext).getModel();
final WorkspaceItemsInfoFetcher fetcher = new WorkspaceItemsInfoFetcher();
launcherModel.enqueueModelUpdateTask(fetcher);
- ArrayList<ItemInfo> workspaceItems;
+ WorkspaceResult workspaceResult;
try {
- workspaceItems = fetcher.mTask.get(5, TimeUnit.SECONDS);
+ workspaceResult = fetcher.mTask.get(5, TimeUnit.SECONDS);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
Log.d(TAG, "Error fetching workspace items info", e);
return;
@@ -284,9 +298,14 @@
// items
ArrayList<ItemInfo> currentWorkspaceItems = new ArrayList<>();
ArrayList<ItemInfo> otherWorkspaceItems = new ArrayList<>();
+ ArrayList<LauncherAppWidgetInfo> currentAppWidgets = new ArrayList<>();
+ ArrayList<LauncherAppWidgetInfo> otherAppWidgets = new ArrayList<>();
- filterCurrentWorkspaceItems(0 /* currentScreenId */, workspaceItems,
- currentWorkspaceItems, otherWorkspaceItems);
+ filterCurrentWorkspaceItems(0 /* currentScreenId */,
+ workspaceResult.mWorkspaceItems, currentWorkspaceItems,
+ otherWorkspaceItems);
+ filterCurrentWorkspaceItems(0 /* currentScreenId */, workspaceResult.mAppWidgets,
+ currentAppWidgets, otherAppWidgets);
sortWorkspaceItemsSpatially(mIdp, currentWorkspaceItems);
for (ItemInfo itemInfo : currentWorkspaceItems) {
@@ -303,6 +322,17 @@
break;
}
}
+ for (ItemInfo itemInfo : currentAppWidgets) {
+ switch (itemInfo.itemType) {
+ case Favorites.ITEM_TYPE_APPWIDGET:
+ case Favorites.ITEM_TYPE_CUSTOM_APPWIDGET:
+ inflateAndAddWidgets((LauncherAppWidgetInfo) itemInfo,
+ workspaceResult.mWidgetsModel);
+ break;
+ default:
+ break;
+ }
+ }
} else {
// Add hotseat icons
for (int i = 0; i < mIdp.numHotseatIcons; i++) {
@@ -349,10 +379,10 @@
}
}
- private static class WorkspaceItemsInfoFetcher implements Callable<ArrayList<ItemInfo>>,
+ private static class WorkspaceItemsInfoFetcher implements Callable<WorkspaceResult>,
LauncherModel.ModelUpdateTask {
- private final FutureTask<ArrayList<ItemInfo>> mTask = new FutureTask<>(this);
+ private final FutureTask<WorkspaceResult> mTask = new FutureTask<>(this);
private LauncherAppState mApp;
private LauncherModel mModel;
@@ -374,14 +404,16 @@
}
@Override
- public ArrayList<ItemInfo> call() throws Exception {
+ public WorkspaceResult call() throws Exception {
if (!mModel.isModelLoaded()) {
Log.d(TAG, "Workspace not loaded, loading now");
mModel.startLoaderForResults(
new LoaderResults(mApp, mBgDataModel, mAllAppsList, new Callbacks[0]));
- return new ArrayList<>();
+ return null;
}
- return mBgDataModel.workspaceItems;
+
+ return new WorkspaceResult(mBgDataModel.workspaceItems, mBgDataModel.appWidgets,
+ mBgDataModel.widgetsModel);
}
}
@@ -389,4 +421,17 @@
view.measure(makeMeasureSpec(width, EXACTLY), makeMeasureSpec(height, EXACTLY));
view.layout(0, 0, width, height);
}
+
+ private static class WorkspaceResult {
+ private final ArrayList<ItemInfo> mWorkspaceItems;
+ private final ArrayList<LauncherAppWidgetInfo> mAppWidgets;
+ private final WidgetsModel mWidgetsModel;
+
+ private WorkspaceResult(ArrayList<ItemInfo> workspaceItems,
+ ArrayList<LauncherAppWidgetInfo> appWidgets, WidgetsModel widgetsModel) {
+ mWorkspaceItems = workspaceItems;
+ mAppWidgets = appWidgets;
+ mWidgetsModel = widgetsModel;
+ }
+ }
}
diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java
index af802ef..6223a23 100644
--- a/src/com/android/launcher3/model/LoaderTask.java
+++ b/src/com/android/launcher3/model/LoaderTask.java
@@ -901,7 +901,8 @@
}
private void loadFolderNames() {
- FolderNameProvider provider = FolderNameProvider.newInstance(mApp.getContext());
+ FolderNameProvider provider = FolderNameProvider.newInstance(mApp.getContext(),
+ mBgAllAppsList.data, mBgDataModel.folders);
synchronized (mBgDataModel) {
for (int i = 0; i < mBgDataModel.folders.size(); i++) {
diff --git a/src/com/android/launcher3/model/PackageItemInfo.java b/src/com/android/launcher3/model/PackageItemInfo.java
index 3ef48cd..2fc064c 100644
--- a/src/com/android/launcher3/model/PackageItemInfo.java
+++ b/src/com/android/launcher3/model/PackageItemInfo.java
@@ -19,6 +19,8 @@
import com.android.launcher3.ItemInfoWithIcon;
import com.android.launcher3.LauncherSettings;
+import java.util.Objects;
+
/**
* Represents a {@link Package} in the widget tray section.
*/
@@ -48,4 +50,17 @@
public PackageItemInfo clone() {
return new PackageItemInfo(this);
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ PackageItemInfo that = (PackageItemInfo) o;
+ return Objects.equals(packageName, that.packageName);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(packageName);
+ }
}
diff --git a/src/com/android/launcher3/views/AbstractSlideInView.java b/src/com/android/launcher3/views/AbstractSlideInView.java
index 9334c46..bdba39c 100644
--- a/src/com/android/launcher3/views/AbstractSlideInView.java
+++ b/src/com/android/launcher3/views/AbstractSlideInView.java
@@ -15,6 +15,8 @@
*/
package com.android.launcher3.views;
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+
import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
import android.animation.Animator;
@@ -62,6 +64,7 @@
protected final ObjectAnimator mOpenCloseAnimator;
protected View mContent;
+ private final View mColorScrim;
protected Interpolator mScrollInterpolator;
// range [0, 1], 0=> completely open, 1=> completely closed
@@ -85,11 +88,30 @@
announceAccessibilityChanges();
}
});
+ int scrimColor = getScrimColor(mLauncher);
+ mColorScrim = scrimColor != -1 ? createColorScrim(mLauncher, scrimColor) : null;
+ }
+
+ protected void attachToContainer() {
+ if (mColorScrim != null) {
+ getPopupContainer().addView(mColorScrim);
+ }
+ getPopupContainer().addView(this);
+ }
+
+ /**
+ * Returns a scrim color for a sliding view. if returned value is -1, no scrim is added.
+ */
+ protected int getScrimColor(Context context) {
+ return -1;
}
protected void setTranslationShift(float translationShift) {
mTranslationShift = translationShift;
mContent.setTranslationY(mTranslationShift * mContent.getHeight());
+ if (mColorScrim != null) {
+ mColorScrim.setAlpha(1 - mTranslationShift);
+ }
}
@Override
@@ -127,7 +149,8 @@
/* SingleAxisSwipeDetector.Listener */
@Override
- public void onDragStart(boolean start) { }
+ public void onDragStart(boolean start) {
+ }
@Override
public boolean onDrag(float displacement) {
@@ -185,9 +208,25 @@
protected void onCloseComplete() {
mIsOpen = false;
getPopupContainer().removeView(this);
+ if (mColorScrim != null) {
+ getPopupContainer().removeView(mColorScrim);
+ }
}
protected BaseDragLayer getPopupContainer() {
return mLauncher.getDragLayer();
}
+
+
+ protected static View createColorScrim(Context context, int bgColor) {
+ View view = new View(context);
+ view.forceHasOverlappingRendering(false);
+ view.setBackgroundColor(bgColor);
+
+ BaseDragLayer.LayoutParams lp = new BaseDragLayer.LayoutParams(MATCH_PARENT, MATCH_PARENT);
+ lp.ignoreInsets = true;
+ view.setLayoutParams(lp);
+
+ return view;
+ }
}
diff --git a/src/com/android/launcher3/views/WorkEduView.java b/src/com/android/launcher3/views/WorkEduView.java
index b6c81ae..81f8327 100644
--- a/src/com/android/launcher3/views/WorkEduView.java
+++ b/src/com/android/launcher3/views/WorkEduView.java
@@ -52,11 +52,15 @@
private static final int WORK_EDU_PERSONAL_APPS = 1;
private static final int WORK_EDU_WORK_APPS = 2;
+ protected static final int FINAL_SCRIM_BG_COLOR = 0x88000000;
+
+
private Rect mInsets = new Rect();
private View mViewWrapper;
private Button mProceedButton;
private TextView mContentText;
private AllAppsPagedView mAllAppsPagedView;
+
private int mNextWorkEduStep = WORK_EDU_PERSONAL_APPS;
@@ -141,10 +145,15 @@
}
private void show() {
- mLauncher.getDragLayer().addView(this);
+ attachToContainer();
animateOpen();
}
+ @Override
+ protected int getScrimColor(Context context) {
+ return FINAL_SCRIM_BG_COLOR;
+ }
+
private void goToFirstPage() {
if (mAllAppsPagedView != null) {
mAllAppsPagedView.snapToPageImmediately(AllAppsContainerView.AdapterHolder.MAIN);
diff --git a/src/com/android/launcher3/widget/BaseWidgetSheet.java b/src/com/android/launcher3/widget/BaseWidgetSheet.java
index 6cae43d..df1a469 100644
--- a/src/com/android/launcher3/widget/BaseWidgetSheet.java
+++ b/src/com/android/launcher3/widget/BaseWidgetSheet.java
@@ -15,8 +15,6 @@
*/
package com.android.launcher3.widget;
-import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
-
import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound;
import static com.android.launcher3.logging.LoggerUtils.newContainerTarget;
@@ -42,7 +40,6 @@
import com.android.launcher3.util.SystemUiController;
import com.android.launcher3.util.Themes;
import com.android.launcher3.views.AbstractSlideInView;
-import com.android.launcher3.views.BaseDragLayer;
/**
* Base class for various widgets popup
@@ -55,11 +52,14 @@
/* Touch handling related member variables. */
private Toast mWidgetInstructionToast;
- protected final View mColorScrim;
-
public BaseWidgetSheet(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
- mColorScrim = createColorScrim(context);
+ }
+
+ protected int getScrimColor(Context context) {
+ WallpaperColorInfo colors = WallpaperColorInfo.INSTANCE.get(context);
+ int alpha = context.getResources().getInteger(R.integer.extracted_color_gradient_alpha);
+ return setColorAlphaBound(colors.getSecondaryColor(), alpha);
}
@Override
@@ -98,16 +98,6 @@
return true;
}
- protected void attachToContainer() {
- getPopupContainer().addView(mColorScrim);
- getPopupContainer().addView(this);
- }
-
- protected void setTranslationShift(float translationShift) {
- super.setTranslationShift(translationShift);
- mColorScrim.setAlpha(1 - mTranslationShift);
- }
-
private boolean beginDraggingWidget(WidgetCell v) {
// Get the widget preview as the drag representation
WidgetImageView image = v.getWidgetView();
@@ -138,7 +128,6 @@
protected void onCloseComplete() {
super.onCloseComplete();
- getPopupContainer().removeView(mColorScrim);
clearNavBarColor();
}
@@ -177,19 +166,4 @@
protected SystemUiController getSystemUiController() {
return mLauncher.getSystemUiController();
}
-
- private static View createColorScrim(Context context) {
- View view = new View(context);
- view.forceHasOverlappingRendering(false);
-
- WallpaperColorInfo colors = WallpaperColorInfo.INSTANCE.get(context);
- int alpha = context.getResources().getInteger(R.integer.extracted_color_gradient_alpha);
- view.setBackgroundColor(setColorAlphaBound(colors.getSecondaryColor(), alpha));
-
- BaseDragLayer.LayoutParams lp = new BaseDragLayer.LayoutParams(MATCH_PARENT, MATCH_PARENT);
- lp.ignoreInsets = true;
- view.setLayoutParams(lp);
-
- return view;
- }
}
diff --git a/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java b/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java
index 282867a..ae32692 100644
--- a/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java
+++ b/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java
@@ -6,6 +6,7 @@
import static com.android.launcher3.pm.ShortcutConfigActivityInfo.queryList;
import android.appwidget.AppWidgetProviderInfo;
+import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Process;
@@ -243,4 +244,16 @@
}
}
}
+
+ public WidgetItem getWidgetProviderInfoByProviderName(
+ ComponentName providerName) {
+ ArrayList<WidgetItem> widgetsList = mWidgetsList.get(
+ new PackageItemInfo(providerName.getPackageName()));
+ for (WidgetItem item : widgetsList) {
+ if (item.componentName.equals(providerName)) {
+ return item;
+ }
+ }
+ return null;
+ }
}
\ No newline at end of file
diff --git a/tests/src/com/android/launcher3/ui/WorkTabTest.java b/tests/src/com/android/launcher3/ui/WorkTabTest.java
index 5aa0090..6fe6739 100644
--- a/tests/src/com/android/launcher3/ui/WorkTabTest.java
+++ b/tests/src/com/android/launcher3/ui/WorkTabTest.java
@@ -73,11 +73,10 @@
mDevice.pressHome();
waitForLauncherCondition("Launcher didn't start", Objects::nonNull);
executeOnLauncher(launcher -> launcher.getStateManager().goToState(ALL_APPS));
-
waitForLauncherCondition("Personal tab is missing",
- launcher -> launcher.getAppsView().isPersonalTabVisible());
+ launcher -> launcher.getAppsView().isPersonalTabVisible(), 60000);
waitForLauncherCondition("Work tab is missing",
- launcher -> launcher.getAppsView().isWorkTabVisible());
+ launcher -> launcher.getAppsView().isWorkTabVisible(), 60000);
}
@Test
@@ -89,7 +88,7 @@
executeOnLauncher(launcher -> launcher.getStateManager().goToState(ALL_APPS));
waitForState("Launcher internal state didn't switch to All Apps", () -> ALL_APPS);
getOnceNotNull("Apps view did not bind",
- launcher -> launcher.getAppsView().getWorkFooterContainer());
+ launcher -> launcher.getAppsView().getWorkFooterContainer(), 60000);
UserManager userManager = getFromLauncher(l -> l.getSystemService(UserManager.class));
assertEquals(2, userManager.getUserProfiles().size());