Merge "Log sub event type to latency logger." into tm-qpr-dev
diff --git a/Android.bp b/Android.bp
index 6267e9f..0bbb3d2 100644
--- a/Android.bp
+++ b/Android.bp
@@ -153,6 +153,7 @@
"androidx.cardview_cardview",
"com.google.android.material_material",
"iconloader_base",
+ "view_capture"
],
manifest: "AndroidManifest-common.xml",
sdk_version: "current",
diff --git a/protos/view_capture.proto b/protos/view_capture.proto
deleted file mode 100644
index f363f36..0000000
--- a/protos/view_capture.proto
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2022 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.view;
-
-option java_outer_classname = "ViewCaptureData";
-
-message ExportedData {
-
- repeated FrameData frameData = 1;
- repeated string classname = 2;
-}
-
-message FrameData {
- optional int64 timestamp = 1;
- optional ViewNode node = 2;
-}
-
-message ViewNode {
- optional int32 classname_index = 1;
- optional int32 hashcode = 2;
-
- repeated ViewNode children = 3;
-
- optional string id = 4;
- optional int32 left = 5;
- optional int32 top = 6;
- optional int32 width = 7;
- optional int32 height = 8;
- optional int32 scrollX = 9;
- optional int32 scrollY = 10;
-
- optional float translationX = 11;
- optional float translationY = 12;
- optional float scaleX = 13 [default = 1];
- optional float scaleY = 14 [default = 1];
- optional float alpha = 15 [default = 1];
-
- optional bool willNotDraw = 16;
- optional bool clipChildren = 17;
- optional int32 visibility = 18;
-
- optional float elevation = 19;
-}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt
index d0e2b22..abd467d 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt
@@ -38,6 +38,8 @@
private var maxBackgroundHeight = context.deviceProfile.taskbarSize.toFloat()
private val transientBackgroundBounds = context.transientTaskbarBounds
+ private val isTransientTaskbar = DisplayController.isTransientTaskbar(context);
+
private var shadowBlur = 0f
private var keyShadowDistance = 0f
private var bottomMargin = 0
@@ -52,7 +54,7 @@
paint.flags = Paint.ANTI_ALIAS_FLAG
paint.style = Paint.Style.FILL
- if (DisplayController.isTransientTaskbar(context)) {
+ if (isTransientTaskbar) {
paint.color = context.getColor(R.color.transient_taskbar_background)
val res = context.resources
@@ -81,7 +83,7 @@
fun draw(canvas: Canvas) {
canvas.save()
canvas.translate(0f, canvas.height - backgroundHeight - bottomMargin)
- if (transientBackgroundBounds.isEmpty) {
+ if (!isTransientTaskbar || transientBackgroundBounds.isEmpty) {
// Draw the background behind taskbar content.
canvas.drawRect(0f, 0f, canvas.width.toFloat(), backgroundHeight, paint)
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index df39111..eaf577b 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -58,6 +58,7 @@
import android.content.res.Configuration;
import android.hardware.SensorManager;
import android.hardware.devicestate.DeviceStateManager;
+import android.media.permission.SafeCloseable;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.IBinder;
@@ -71,10 +72,12 @@
import androidx.annotation.Nullable;
+import com.android.app.viewcapture.ViewCapture;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.LauncherState;
+import com.android.launcher3.LauncherWidgetHolder;
import com.android.launcher3.QuickstepAccessibilityDelegate;
import com.android.launcher3.QuickstepTransitionManager;
import com.android.launcher3.R;
@@ -119,10 +122,8 @@
import com.android.launcher3.util.PendingRequestArgs;
import com.android.launcher3.util.PendingSplitSelectInfo;
import com.android.launcher3.util.RunnableList;
-import com.android.launcher3.util.SafeCloseable;
import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
import com.android.launcher3.util.TouchController;
-import com.android.launcher3.widget.LauncherAppWidgetHost;
import com.android.quickstep.OverviewCommandHelper;
import com.android.quickstep.RecentsModel;
import com.android.quickstep.SystemUiProxy;
@@ -135,7 +136,6 @@
import com.android.quickstep.util.RemoteFadeOutAnimationListener;
import com.android.quickstep.util.SplitSelectStateController;
import com.android.quickstep.util.TISBindHelper;
-import com.android.quickstep.util.ViewCapture;
import com.android.quickstep.views.OverviewActionsView;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
@@ -402,7 +402,7 @@
super.onDestroy();
mHotseatPredictionController.destroy();
- mViewCapture.close();
+ if (mViewCapture != null) mViewCapture.close();
}
@Override
@@ -487,11 +487,11 @@
return new QuickstepAtomicAnimationFactory(this);
}
- protected LauncherAppWidgetHost createAppWidgetHost() {
- LauncherAppWidgetHost appWidgetHost = super.createAppWidgetHost();
- ApiWrapper.setHostInteractionHandler(appWidgetHost,
- new QuickstepInteractionHandler(this));
- return appWidgetHost;
+ @Override
+ protected LauncherWidgetHolder createAppWidgetHolder() {
+ LauncherWidgetHolder appWidgetHolder = super.createAppWidgetHolder();
+ appWidgetHolder.setInteractionHandler(new QuickstepInteractionHandler(this));
+ return appWidgetHolder;
}
@Override
@@ -503,7 +503,9 @@
}
addMultiWindowModeChangedListener(mDepthController);
initUnfoldTransitionProgressProvider();
- mViewCapture = ViewCapture.INSTANCE.get(this).startCapture(getWindow());
+ if (FeatureFlags.CONTINUOUS_VIEW_TREE_CAPTURE.get()) {
+ mViewCapture = ViewCapture.getInstance().startCapture(getWindow());
+ }
}
@Override
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index 80db362..e9f9d80 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -67,6 +67,7 @@
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
+import com.android.app.viewcapture.ViewCapture;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
@@ -103,7 +104,6 @@
import com.android.quickstep.util.ProtoTracer;
import com.android.quickstep.util.ProxyScreenStatusProvider;
import com.android.quickstep.util.SplitScreenBounds;
-import com.android.quickstep.util.ViewCapture;
import com.android.systemui.shared.recents.IOverviewProxy;
import com.android.systemui.shared.recents.ISystemUiProxy;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -1238,7 +1238,9 @@
}
mTaskbarManager.dumpLogs("", pw);
- ViewCapture.INSTANCE.get(this).dump(pw, fd);
+ if (FeatureFlags.CONTINUOUS_VIEW_TREE_CAPTURE.get()) {
+ ViewCapture.getInstance().dump(pw, fd, this);
+ }
}
}
diff --git a/quickstep/src/com/android/quickstep/util/ViewCapture.java b/quickstep/src/com/android/quickstep/util/ViewCapture.java
deleted file mode 100644
index ba7d7f5..0000000
--- a/quickstep/src/com/android/quickstep/util/ViewCapture.java
+++ /dev/null
@@ -1,541 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.quickstep.util;
-
-import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
-import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
-import static com.android.launcher3.util.Executors.createAndStartNewLooper;
-
-import static java.util.stream.Collectors.toList;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.os.Looper;
-import android.os.Process;
-import android.os.SystemClock;
-import android.os.Trace;
-import android.text.TextUtils;
-import android.util.Base64;
-import android.util.Base64OutputStream;
-import android.util.Log;
-import android.util.Pair;
-import android.util.SparseArray;
-import android.view.View;
-import android.view.View.OnAttachStateChangeListener;
-import android.view.ViewGroup;
-import android.view.ViewTreeObserver.OnDrawListener;
-import android.view.Window;
-
-import androidx.annotation.UiThread;
-import androidx.annotation.WorkerThread;
-
-import com.android.launcher3.config.FeatureFlags;
-import com.android.launcher3.util.LooperExecutor;
-import com.android.launcher3.util.MainThreadInitializedObject;
-import com.android.launcher3.util.SafeCloseable;
-import com.android.launcher3.view.ViewCaptureData.ExportedData;
-import com.android.launcher3.view.ViewCaptureData.FrameData;
-import com.android.launcher3.view.ViewCaptureData.ViewNode;
-
-import java.io.FileDescriptor;
-import java.io.FileOutputStream;
-import java.io.OutputStream;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.Executor;
-import java.util.concurrent.FutureTask;
-import java.util.function.Consumer;
-import java.util.zip.GZIPOutputStream;
-
-/**
- * Utility class for capturing view data every frame
- */
-public class ViewCapture {
-
- private static final String TAG = "ViewCapture";
-
- // These flags are copies of two private flags in the View class.
- private static final int PFLAG_INVALIDATED = 0x80000000;
- private static final int PFLAG_DIRTY_MASK = 0x00200000;
-
- // Number of frames to keep in memory
- private static final int MEMORY_SIZE = 2000;
- // Initial size of the reference pool. This is at least be 5 * total number of views in
- // Launcher. This allows the first free frames avoid object allocation during view capture.
- private static final int INIT_POOL_SIZE = 300;
-
- public static final MainThreadInitializedObject<ViewCapture> INSTANCE =
- new MainThreadInitializedObject<>(ViewCapture::new);
-
- private final List<WindowListener> mListeners = new ArrayList<>();
-
- private final Context mContext;
- private final Executor mExecutor;
-
- // Pool used for capturing view tree on the UI thread.
- private ViewRef mPool = new ViewRef();
-
- private ViewCapture(Context context) {
- mContext = context;
- if (FeatureFlags.CONTINUOUS_VIEW_TREE_CAPTURE.get()) {
- Looper looper = createAndStartNewLooper("ViewCapture",
- Process.THREAD_PRIORITY_FOREGROUND);
- mExecutor = new LooperExecutor(looper);
- mExecutor.execute(this::initPool);
- } else {
- mExecutor = UI_HELPER_EXECUTOR;
- }
- }
-
- @UiThread
- private void addToPool(ViewRef start, ViewRef end) {
- end.next = mPool;
- mPool = start;
- }
-
- @WorkerThread
- private void initPool() {
- ViewRef start = new ViewRef();
- ViewRef current = start;
-
- for (int i = 0; i < INIT_POOL_SIZE; i++) {
- current.next = new ViewRef();
- current = current.next;
- }
-
- ViewRef finalCurrent = current;
- MAIN_EXECUTOR.execute(() -> addToPool(start, finalCurrent));
- }
-
- /**
- * Attaches the ViewCapture to the provided window and returns a handle to detach the listener
- */
- public SafeCloseable startCapture(Window window) {
- String title = window.getAttributes().getTitle().toString();
- String name = TextUtils.isEmpty(title) ? window.toString() : title;
- return startCapture(window.getDecorView(), name);
- }
-
- /**
- * Attaches the ViewCapture to the provided window and returns a handle to detach the listener
- */
- public SafeCloseable startCapture(View view, String name) {
- if (!FeatureFlags.CONTINUOUS_VIEW_TREE_CAPTURE.get()) {
- return () -> { };
- }
-
- WindowListener listener = new WindowListener(view, name);
- mExecutor.execute(() -> MAIN_EXECUTOR.execute(listener::attachToRoot));
- mListeners.add(listener);
- return () -> {
- mListeners.remove(listener);
- listener.destroy();
- };
- }
-
- /**
- * Dumps all the active view captures
- */
- public void dump(PrintWriter writer, FileDescriptor out) {
- if (!FeatureFlags.CONTINUOUS_VIEW_TREE_CAPTURE.get()) {
- return;
- }
- ViewIdProvider idProvider = new ViewIdProvider(mContext.getResources());
-
- // Collect all the tasks first so that all the tasks are posted on the executor
- List<Pair<String, FutureTask<ExportedData>>> tasks = mListeners.stream()
- .map(l -> {
- FutureTask<ExportedData> task =
- new FutureTask<ExportedData>(() -> l.dumpToProto(idProvider));
- mExecutor.execute(task);
- return Pair.create(l.name, task);
- })
- .collect(toList());
-
- tasks.forEach(pair -> {
- writer.println();
- writer.println(" ContinuousViewCapture:");
- writer.println(" window " + pair.first + ":");
- writer.println(" pkg:" + mContext.getPackageName());
- writer.print(" data:");
- writer.flush();
- try (OutputStream os = new FileOutputStream(out)) {
- ExportedData data = pair.second.get();
- OutputStream encodedOS = new GZIPOutputStream(new Base64OutputStream(os,
- Base64.NO_CLOSE | Base64.NO_PADDING | Base64.NO_WRAP));
- data.writeTo(encodedOS);
- encodedOS.close();
- os.flush();
- } catch (Exception e) {
- Log.e(TAG, "Error capturing proto", e);
- }
- writer.println();
- writer.println("--end--");
- });
- }
-
- private class WindowListener implements OnDrawListener {
-
- private final View mRoot;
- public final String name;
-
- private final ViewRef mViewRef = new ViewRef();
-
- private int mFrameIndexBg = -1;
- private boolean mIsFirstFrame = true;
- private final long[] mFrameTimesBg = new long[MEMORY_SIZE];
- private final ViewPropertyRef[] mNodesBg = new ViewPropertyRef[MEMORY_SIZE];
-
- private boolean mDestroyed = false;
- private final Consumer<ViewRef> mCaptureCallback = this::captureViewPropertiesBg;
-
- WindowListener(View view, String name) {
- mRoot = view;
- this.name = name;
- }
-
- @Override
- public void onDraw() {
- Trace.beginSection("view_capture");
- captureViewTree(mRoot, mViewRef);
- ViewRef captured = mViewRef.next;
- if (captured != null) {
- captured.callback = mCaptureCallback;
- captured.creationTime = SystemClock.uptimeMillis();
- mExecutor.execute(captured);
- }
- mIsFirstFrame = false;
- Trace.endSection();
- }
-
- /**
- * Captures the View property on the background thread, and transfer all the ViewRef objects
- * back to the pool
- */
- @WorkerThread
- private void captureViewPropertiesBg(ViewRef viewRefStart) {
- long time = viewRefStart.creationTime;
- mFrameIndexBg++;
- if (mFrameIndexBg >= MEMORY_SIZE) {
- mFrameIndexBg = 0;
- }
- mFrameTimesBg[mFrameIndexBg] = time;
-
- ViewPropertyRef recycle = mNodesBg[mFrameIndexBg];
-
- ViewPropertyRef resultStart = null;
- ViewPropertyRef resultEnd = null;
-
- ViewRef viewRefEnd = viewRefStart;
- while (viewRefEnd != null) {
- ViewPropertyRef propertyRef = recycle;
- if (propertyRef == null) {
- propertyRef = new ViewPropertyRef();
- } else {
- recycle = recycle.next;
- propertyRef.next = null;
- }
-
- ViewPropertyRef copy = null;
- if (viewRefEnd.childCount < 0) {
- copy = findInLastFrame(viewRefEnd.view.hashCode());
- viewRefEnd.childCount = (copy != null) ? copy.childCount : 0;
- }
- viewRefEnd.transferTo(propertyRef);
-
- if (resultStart == null) {
- resultStart = propertyRef;
- resultEnd = resultStart;
- } else {
- resultEnd.next = propertyRef;
- resultEnd = resultEnd.next;
- }
-
- if (copy != null) {
- int pending = copy.childCount;
- while (pending > 0) {
- copy = copy.next;
- pending = pending - 1 + copy.childCount;
-
- propertyRef = recycle;
- if (propertyRef == null) {
- propertyRef = new ViewPropertyRef();
- } else {
- recycle = recycle.next;
- propertyRef.next = null;
- }
-
- copy.transferTo(propertyRef);
-
- resultEnd.next = propertyRef;
- resultEnd = resultEnd.next;
- }
- }
-
- if (viewRefEnd.next == null) {
- // The compiler will complain about using a non-final variable from
- // an outer class in a lambda if we pass in viewRefEnd directly.
- final ViewRef finalViewRefEnd = viewRefEnd;
- MAIN_EXECUTOR.execute(() -> addToPool(viewRefStart, finalViewRefEnd));
- break;
- }
- viewRefEnd = viewRefEnd.next;
- }
- mNodesBg[mFrameIndexBg] = resultStart;
- }
-
- private ViewPropertyRef findInLastFrame(int hashCode) {
- int lastFrameIndex = (mFrameIndexBg == 0) ? MEMORY_SIZE - 1 : mFrameIndexBg - 1;
- ViewPropertyRef viewPropertyRef = mNodesBg[lastFrameIndex];
- while (viewPropertyRef != null && viewPropertyRef.hashCode != hashCode) {
- viewPropertyRef = viewPropertyRef.next;
- }
- return viewPropertyRef;
- }
-
- void attachToRoot() {
- if (mRoot.isAttachedToWindow()) {
- mRoot.getViewTreeObserver().addOnDrawListener(this);
- } else {
- mRoot.addOnAttachStateChangeListener(new OnAttachStateChangeListener() {
- @Override
- public void onViewAttachedToWindow(View v) {
- if (!mDestroyed) {
- mRoot.getViewTreeObserver().addOnDrawListener(WindowListener.this);
- }
- mRoot.removeOnAttachStateChangeListener(this);
- }
-
- @Override
- public void onViewDetachedFromWindow(View v) { }
- });
- }
- }
-
- void destroy() {
- mRoot.getViewTreeObserver().removeOnDrawListener(this);
- mDestroyed = true;
- }
-
- @WorkerThread
- private ExportedData dumpToProto(ViewIdProvider idProvider) {
- ExportedData.Builder dataBuilder = ExportedData.newBuilder();
- ArrayList<Class> classList = new ArrayList<>();
-
- int size = (mNodesBg[MEMORY_SIZE - 1] == null) ? mFrameIndexBg + 1 : MEMORY_SIZE;
- for (int i = size - 1; i >= 0; i--) {
- int index = (MEMORY_SIZE + mFrameIndexBg - i) % MEMORY_SIZE;
- ViewNode.Builder nodeBuilder = ViewNode.newBuilder();
- mNodesBg[index].toProto(idProvider, classList, nodeBuilder);
- dataBuilder.addFrameData(FrameData.newBuilder()
- .setNode(nodeBuilder)
- .setTimestamp(mFrameTimesBg[index]));
- }
- return dataBuilder
- .addAllClassname(classList.stream().map(Class::getName).collect(toList()))
- .build();
- }
-
- private ViewRef captureViewTree(View view, ViewRef start) {
- ViewRef ref;
- if (mPool != null) {
- ref = mPool;
- mPool = mPool.next;
- ref.next = null;
- } else {
- ref = new ViewRef();
- }
- ref.view = view;
- start.next = ref;
- if (view instanceof ViewGroup) {
- ViewGroup parent = (ViewGroup) view;
- // If a view has not changed since the last frame, we will copy
- // its children from the last processed frame's data.
- if ((view.mPrivateFlags & (PFLAG_INVALIDATED | PFLAG_DIRTY_MASK)) == 0
- && !mIsFirstFrame) {
- // A negative child count is the signal to copy this view from the last frame.
- ref.childCount = -parent.getChildCount();
- return ref;
- }
- ViewRef result = ref;
- int childCount = ref.childCount = parent.getChildCount();
- for (int i = 0; i < childCount; i++) {
- result = captureViewTree(parent.getChildAt(i), result);
- }
- return result;
- } else {
- ref.childCount = 0;
- return ref;
- }
- }
- }
-
- private static class ViewPropertyRef {
- // We store reference in memory to avoid generating and storing too many strings
- public Class clazz;
- public int hashCode;
- public int childCount = 0;
-
- public int id;
- public int left, top, right, bottom;
- public int scrollX, scrollY;
-
- public float translateX, translateY;
- public float scaleX, scaleY;
- public float alpha;
- public float elevation;
-
- public int visibility;
- public boolean willNotDraw;
- public boolean clipChildren;
-
- public ViewPropertyRef next;
-
- public void transferTo(ViewPropertyRef out) {
- out.clazz = this.clazz;
- out.hashCode = this.hashCode;
- out.childCount = this.childCount;
- out.id = this.id;
- out.left = this.left;
- out.top = this.top;
- out.right = this.right;
- out.bottom = this.bottom;
- out.scrollX = this.scrollX;
- out.scrollY = this.scrollY;
- out.scaleX = this.scaleX;
- out.scaleY = this.scaleY;
- out.translateX = this.translateX;
- out.translateY = this.translateY;
- out.alpha = this.alpha;
- out.visibility = this.visibility;
- out.willNotDraw = this.willNotDraw;
- out.clipChildren = this.clipChildren;
- out.elevation = this.elevation;
- }
-
- /**
- * Converts the data to the proto representation and returns the next property ref
- * at the end of the iteration.
- * @return
- */
- public ViewPropertyRef toProto(ViewIdProvider idProvider, ArrayList<Class> classList,
- ViewNode.Builder outBuilder) {
- int classnameIndex = classList.indexOf(clazz);
- if (classnameIndex < 0) {
- classnameIndex = classList.size();
- classList.add(clazz);
- }
- outBuilder
- .setClassnameIndex(classnameIndex)
- .setHashcode(hashCode)
- .setId(idProvider.getName(id))
- .setLeft(left)
- .setTop(top)
- .setWidth(right - left)
- .setHeight(bottom - top)
- .setTranslationX(translateX)
- .setTranslationY(translateY)
- .setScaleX(scaleX)
- .setScaleY(scaleY)
- .setAlpha(alpha)
- .setVisibility(visibility)
- .setWillNotDraw(willNotDraw)
- .setElevation(elevation)
- .setClipChildren(clipChildren);
-
- ViewPropertyRef result = next;
- for (int i = 0; (i < childCount) && (result != null); i++) {
- ViewNode.Builder childBuilder = ViewNode.newBuilder();
- result = result.toProto(idProvider, classList, childBuilder);
- outBuilder.addChildren(childBuilder);
- }
- return result;
- }
- }
-
- private static class ViewRef implements Runnable {
- public View view;
- public int childCount = 0;
- public ViewRef next;
-
- public Consumer<ViewRef> callback = null;
- public long creationTime = 0;
-
- public void transferTo(ViewPropertyRef out) {
- out.childCount = this.childCount;
-
- View view = this.view;
- this.view = null;
-
- out.clazz = view.getClass();
- out.hashCode = view.hashCode();
- out.id = view.getId();
- out.left = view.getLeft();
- out.top = view.getTop();
- out.right = view.getRight();
- out.bottom = view.getBottom();
- out.scrollX = view.getScrollX();
- out.scrollY = view.getScrollY();
-
- out.translateX = view.getTranslationX();
- out.translateY = view.getTranslationY();
- out.scaleX = view.getScaleX();
- out.scaleY = view.getScaleY();
- out.alpha = view.getAlpha();
- out.elevation = view.getElevation();
-
- out.visibility = view.getVisibility();
- out.willNotDraw = view.willNotDraw();
- }
-
- @Override
- public void run() {
- Consumer<ViewRef> oldCallback = callback;
- callback = null;
- if (oldCallback != null) {
- oldCallback.accept(this);
- }
- }
- }
-
- private static final class ViewIdProvider {
-
- private final SparseArray<String> mNames = new SparseArray<>();
- private final Resources mRes;
-
- ViewIdProvider(Resources res) {
- mRes = res;
- }
-
- String getName(int id) {
- String name = mNames.get(id);
- if (name == null) {
- if (id >= 0) {
- try {
- name = mRes.getResourceTypeName(id) + '/' + mRes.getResourceEntryName(id);
- } catch (Resources.NotFoundException e) {
- name = "id/" + "0x" + Integer.toHexString(id).toUpperCase();
- }
- } else {
- name = "NO_ID";
- }
- mNames.put(id, name);
- }
- return name;
- }
- }
-}
diff --git a/quickstep/src/com/android/quickstep/views/DesktopTaskView.java b/quickstep/src/com/android/quickstep/views/DesktopTaskView.java
index 5167bd7..2abd715 100644
--- a/quickstep/src/com/android/quickstep/views/DesktopTaskView.java
+++ b/quickstep/src/com/android/quickstep/views/DesktopTaskView.java
@@ -437,7 +437,7 @@
}
@Override
- protected void setIconAndDimTransitionProgress(float progress, boolean invert) {
+ protected void setIconsAndBannersTransitionProgress(float progress, boolean invert) {
// no-op
}
diff --git a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
index 64b5e0b..2cada0a 100644
--- a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
+++ b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
@@ -316,8 +316,8 @@
}
@Override
- protected void setIconAndDimTransitionProgress(float progress, boolean invert) {
- super.setIconAndDimTransitionProgress(progress, invert);
+ protected void setIconsAndBannersTransitionProgress(float progress, boolean invert) {
+ super.setIconsAndBannersTransitionProgress(progress, invert);
// Value set by super call
float scale = mIconView.getAlpha();
mIconView2.setAlpha(scale);
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index 0fdd469..527a0d1 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -19,6 +19,7 @@
import static android.view.Display.DEFAULT_DISPLAY;
import static android.widget.Toast.LENGTH_SHORT;
+import static com.android.launcher3.LauncherState.BACKGROUND_APP;
import static com.android.launcher3.Utilities.comp;
import static com.android.launcher3.Utilities.getDescendantCoordRelativeToAncestor;
import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
@@ -172,7 +173,7 @@
new FloatProperty<TaskView>("focusTransition") {
@Override
public void setValue(TaskView taskView, float v) {
- taskView.setIconAndDimTransitionProgress(v, false /* invert */);
+ taskView.setIconsAndBannersTransitionProgress(v, false /* invert */);
}
@Override
@@ -954,7 +955,11 @@
return deviceProfile.isTablet && !isFocusedTask();
}
- protected void setIconAndDimTransitionProgress(float progress, boolean invert) {
+ /**
+ * Called to animate a smooth transition when going directly from an app into Overview (and
+ * vice versa). Icons fade in, and DWB banners slide in with a "shift up" animation.
+ */
+ protected void setIconsAndBannersTransitionProgress(float progress, boolean invert) {
if (invert) {
progress = 1 - progress;
}
@@ -998,7 +1003,7 @@
if (mIconAndDimAnimator != null) {
mIconAndDimAnimator.cancel();
}
- setIconAndDimTransitionProgress(iconScale, invert);
+ setIconsAndBannersTransitionProgress(iconScale, invert);
}
protected void resetPersistentViewTransforms() {
@@ -1418,6 +1423,12 @@
mIconView.setVisibility(progress < 1 ? VISIBLE : INVISIBLE);
mSnapshotView.getTaskOverlay().setFullscreenProgress(progress);
+ // Animate icons and DWB banners in/out, except in QuickSwitch state, when tiles are
+ // oversized and banner would look disproportionately large.
+ if (mActivity.getStateManager().getState() != BACKGROUND_APP) {
+ setIconsAndBannersTransitionProgress(progress, true);
+ }
+
updateSnapshotRadius();
}
diff --git a/src/com/android/launcher3/AppWidgetResizeFrame.java b/src/com/android/launcher3/AppWidgetResizeFrame.java
index 555fbb4..76a91c0 100644
--- a/src/com/android/launcher3/AppWidgetResizeFrame.java
+++ b/src/com/android/launcher3/AppWidgetResizeFrame.java
@@ -249,11 +249,11 @@
/* widgetHandler= */ null,
(ItemInfo) mWidgetView.getTag()));
mLauncher
- .getAppWidgetHost()
- .startConfigActivity(
- mLauncher,
- mWidgetView.getAppWidgetId(),
- Launcher.REQUEST_RECONFIGURE_APPWIDGET);
+ .getAppWidgetHolder()
+ .startConfigActivity(
+ mLauncher,
+ mWidgetView.getAppWidgetId(),
+ Launcher.REQUEST_RECONFIGURE_APPWIDGET);
});
if (!hasSeenReconfigurableWidgetEducationTip()) {
post(() -> {
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 1259d6e..7269d14 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -205,7 +205,6 @@
import com.android.launcher3.views.FloatingSurfaceView;
import com.android.launcher3.views.OptionsPopupView;
import com.android.launcher3.views.ScrimView;
-import com.android.launcher3.widget.LauncherAppWidgetHost;
import com.android.launcher3.widget.LauncherAppWidgetHostView;
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import com.android.launcher3.widget.PendingAddShortcutInfo;
@@ -317,7 +316,7 @@
DragLayer mDragLayer;
private WidgetManagerHelper mAppWidgetManager;
- private LauncherAppWidgetHost mAppWidgetHost;
+ private LauncherWidgetHolder mAppWidgetHolder;
private final int[] mTmpAddItemCellCoordinates = new int[2];
@@ -482,8 +481,8 @@
mOnboardingPrefs = createOnboardingPrefs(mSharedPrefs);
mAppWidgetManager = new WidgetManagerHelper(this);
- mAppWidgetHost = createAppWidgetHost();
- mAppWidgetHost.startListening();
+ mAppWidgetHolder = createAppWidgetHolder();
+ mAppWidgetHolder.startListening();
setupViews();
crossFadeWithPreviousAppearance();
@@ -963,7 +962,7 @@
AppWidgetHostView boundWidget = null;
if (resultCode == RESULT_OK) {
animationType = Workspace.COMPLETE_TWO_STAGE_WIDGET_DROP_ANIMATION;
- final AppWidgetHostView layout = mAppWidgetHost.createView(this, appWidgetId,
+ final AppWidgetHostView layout = mAppWidgetHolder.createView(this, appWidgetId,
requestArgs.getWidgetHandler().getProviderInfo(this));
boundWidget = layout;
onCompleteRunnable = new Runnable() {
@@ -974,7 +973,7 @@
}
};
} else if (resultCode == RESULT_CANCELED) {
- mAppWidgetHost.deleteAppWidgetId(appWidgetId);
+ mAppWidgetHolder.deleteAppWidgetId(appWidgetId);
animationType = Workspace.CANCEL_TWO_STAGE_WIDGET_DROP_ANIMATION;
}
if (mDragLayer.getAnimatedView() != null) {
@@ -997,7 +996,7 @@
}
hideKeyboard();
logStopAndResume(false /* isResume */);
- mAppWidgetHost.setActivityStarted(false);
+ mAppWidgetHolder.setActivityStarted(false);
NotificationListener.removeNotificationsChangedListener(getPopupDataProvider());
}
@@ -1010,7 +1009,7 @@
mOverlayManager.onActivityStarted(this);
}
- mAppWidgetHost.setActivityStarted(true);
+ mAppWidgetHolder.setActivityStarted(true);
TraceHelper.INSTANCE.endSection(traceToken);
}
@@ -1030,7 +1029,7 @@
NotificationListener.addNotificationsChangedListener(mPopupDataProvider);
DiscoveryBounce.showForHomeIfNeeded(this);
- mAppWidgetHost.setActivityResumed(true);
+ mAppWidgetHolder.setActivityResumed(true);
}
private void logStopAndResume(boolean isResume) {
@@ -1145,7 +1144,7 @@
@Override
public void onStateSetEnd(LauncherState state) {
super.onStateSetEnd(state);
- getAppWidgetHost().setStateIsNormal(state == LauncherState.NORMAL);
+ getAppWidgetHolder().setStateIsNormal(state == LauncherState.NORMAL);
getWorkspace().setClipChildren(!state.hasFlag(FLAG_MULTI_PAGE));
finishAutoCancelActionMode();
@@ -1210,7 +1209,7 @@
if (!mDeferOverlayCallbacks) {
mOverlayManager.onActivityPaused(this);
}
- mAppWidgetHost.setActivityResumed(false);
+ mAppWidgetHolder.setActivityResumed(false);
}
/**
@@ -1435,7 +1434,7 @@
if (hostView == null) {
// Perform actual inflation because we're live
- hostView = mAppWidgetHost.createView(this, appWidgetId, appWidgetInfo);
+ hostView = mAppWidgetHolder.createView(this, appWidgetId, appWidgetInfo);
}
LauncherAppWidgetInfo launcherInfo;
@@ -1566,12 +1565,12 @@
return mScrimView;
}
- public LauncherAppWidgetHost getAppWidgetHost() {
- return mAppWidgetHost;
+ public LauncherWidgetHolder getAppWidgetHolder() {
+ return mAppWidgetHolder;
}
- protected LauncherAppWidgetHost createAppWidgetHost() {
- return new LauncherAppWidgetHost(this,
+ protected LauncherWidgetHolder createAppWidgetHolder() {
+ return new LauncherWidgetHolder(this,
appWidgetId -> getWorkspace().removeWidget(appWidgetId));
}
@@ -1733,7 +1732,7 @@
mRotationHelper.destroy();
try {
- mAppWidgetHost.stopListening();
+ mAppWidgetHolder.stopListening();
} catch (NullPointerException ex) {
Log.w(TAG, "problem while stopping AppWidgetHost during Launcher destruction", ex);
}
@@ -1908,7 +1907,7 @@
appWidgetId = CustomWidgetManager.INSTANCE.get(this).getWidgetIdForCustomProvider(
info.componentName);
} else {
- appWidgetId = getAppWidgetHost().allocateAppWidgetId();
+ appWidgetId = getAppWidgetHolder().allocateAppWidgetId();
}
Bundle options = info.bindOptions;
@@ -2022,7 +2021,7 @@
final LauncherAppWidgetInfo widgetInfo = (LauncherAppWidgetInfo) itemInfo;
mWorkspace.removeWorkspaceItem(v);
if (deleteFromDb) {
- getModelWriter().deleteWidgetInfo(widgetInfo, getAppWidgetHost(), reason);
+ getModelWriter().deleteWidgetInfo(widgetInfo, getAppWidgetHolder(), reason);
}
} else {
return false;
@@ -2280,7 +2279,7 @@
mWorkspace.clearDropTargets();
mWorkspace.removeAllWorkspaceScreens();
- mAppWidgetHost.clearViews();
+ mAppWidgetHolder.clearViews();
if (mHotseat != null) {
mHotseat.resetLayout(getDeviceProfile().isVerticalBarLayout());
@@ -2587,7 +2586,7 @@
if (item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_ID_NOT_VALID)) {
if (!item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_ID_ALLOCATED)) {
// Id has not been allocated yet. Allocate a new id.
- item.appWidgetId = mAppWidgetHost.allocateAppWidgetId();
+ item.appWidgetId = mAppWidgetHolder.allocateAppWidgetId();
item.restoreStatus |= LauncherAppWidgetInfo.FLAG_ID_ALLOCATED;
// Also try to bind the widget. If the bind fails, the user will be shown
@@ -2649,18 +2648,18 @@
// Verify that we own the widget
if (appWidgetInfo == null) {
FileLog.e(TAG, "Removing invalid widget: id=" + item.appWidgetId);
- getModelWriter().deleteWidgetInfo(item, getAppWidgetHost(), removalReason);
+ getModelWriter().deleteWidgetInfo(item, getAppWidgetHolder(), removalReason);
return null;
}
item.minSpanX = appWidgetInfo.minSpanX;
item.minSpanY = appWidgetInfo.minSpanY;
- view = mAppWidgetHost.createView(this, item.appWidgetId, appWidgetInfo);
+ view = mAppWidgetHolder.createView(this, item.appWidgetId, appWidgetInfo);
} else if (!item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_ID_NOT_VALID)
&& appWidgetInfo != null) {
- mAppWidgetHost.addPendingView(item.appWidgetId,
+ mAppWidgetHolder.addPendingView(item.appWidgetId,
new PendingAppWidgetHostView(this, item, mIconCache, false));
- view = mAppWidgetHost.createView(this, item.appWidgetId, appWidgetInfo);
+ view = mAppWidgetHolder.createView(this, item.appWidgetId, appWidgetInfo);
} else {
view = new PendingAppWidgetHostView(this, item, mIconCache, false);
}
@@ -3018,7 +3017,8 @@
writer.println(prefix + "\tmPendingRequestArgs=" + mPendingRequestArgs
+ " mPendingActivityResult=" + mPendingActivityResult);
writer.println(prefix + "\tmRotationHelper: " + mRotationHelper);
- writer.println(prefix + "\tmAppWidgetHost.isListening: " + mAppWidgetHost.isListening());
+ writer.println(prefix + "\tmAppWidgetHolder.isListening: "
+ + mAppWidgetHolder.isListening());
// Extra logging for general debugging
mDragLayer.dump(prefix, writer);
diff --git a/src/com/android/launcher3/LauncherWidgetHolder.java b/src/com/android/launcher3/LauncherWidgetHolder.java
new file mode 100644
index 0000000..5fcd46f
--- /dev/null
+++ b/src/com/android/launcher3/LauncherWidgetHolder.java
@@ -0,0 +1,187 @@
+/**
+ * Copyright (C) 2022 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;
+
+import android.appwidget.AppWidgetHostView;
+import android.appwidget.AppWidgetProviderInfo;
+import android.content.Context;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.launcher3.uioverrides.ApiWrapper;
+import com.android.launcher3.widget.LauncherAppWidgetHost;
+import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
+import com.android.launcher3.widget.PendingAppWidgetHostView;
+
+import java.util.function.IntConsumer;
+
+/**
+ * A wrapper for LauncherAppWidgetHost. This class is created so the AppWidgetHost could run in
+ * background.
+ */
+public class LauncherWidgetHolder {
+ @NonNull
+ private final LauncherAppWidgetHost mWidgetHost;
+
+ public LauncherWidgetHolder(@NonNull Context context) {
+ this(context, null);
+ }
+
+ public LauncherWidgetHolder(@NonNull Context context,
+ @Nullable IntConsumer appWidgetRemovedCallback) {
+ mWidgetHost = new LauncherAppWidgetHost(context, appWidgetRemovedCallback);
+ }
+
+ /**
+ * Starts listening to the widget updates from the server side
+ */
+ public void startListening() {
+ mWidgetHost.startListening();
+ }
+
+ /**
+ * Set the STARTED state of the widget host
+ * @param isStarted True if setting the host as started, false otherwise
+ */
+ public void setActivityStarted(boolean isStarted) {
+ mWidgetHost.setActivityStarted(isStarted);
+ }
+
+ /**
+ * Set the RESUMED state of the widget host
+ * @param isResumed True if setting the host as resumed, false otherwise
+ */
+ public void setActivityResumed(boolean isResumed) {
+ mWidgetHost.setActivityResumed(isResumed);
+ }
+
+ /**
+ * Set the NORMAL state of the widget host
+ * @param isNormal True if setting the host to be in normal state, false otherwise
+ */
+ public void setStateIsNormal(boolean isNormal) {
+ mWidgetHost.setStateIsNormal(isNormal);
+ }
+
+ /**
+ * Delete the specified app widget from the host
+ * @param appWidgetId The ID of the app widget to be deleted
+ */
+ public void deleteAppWidgetId(int appWidgetId) {
+ mWidgetHost.deleteAppWidgetId(appWidgetId);
+ }
+
+ /**
+ * Add the pending view to the host for complete configuration in further steps
+ * @param appWidgetId The ID of the specified app widget
+ * @param view The {@link PendingAppWidgetHostView} of the app widget
+ */
+ public void addPendingView(int appWidgetId, @NonNull PendingAppWidgetHostView view) {
+ mWidgetHost.addPendingView(appWidgetId, view);
+ }
+
+ /**
+ * @return True if the host is listening to the widget updates, false otherwise
+ */
+ public boolean isListening() {
+ return mWidgetHost.isListening();
+ }
+
+ /**
+ * @return The allocated app widget id if allocation is successful, returns -1 otherwise
+ */
+ public int allocateAppWidgetId() {
+ return mWidgetHost.allocateAppWidgetId();
+ }
+
+ /**
+ * Add a listener that is triggered when the providers of the widgets are changed
+ * @param listener The listener that notifies when the providers changed
+ */
+ public void addProviderChangeListener(
+ @NonNull LauncherAppWidgetHost.ProviderChangedListener listener) {
+ mWidgetHost.addProviderChangeListener(listener);
+ }
+
+ /**
+ * Remove the specified listener from the host
+ * @param listener The listener that is to be removed from the host
+ */
+ public void removeProviderChangeListener(
+ LauncherAppWidgetHost.ProviderChangedListener listener) {
+ mWidgetHost.removeProviderChangeListener(listener);
+ }
+
+ /**
+ * Starts the configuration activity for the widget
+ * @param activity The activity in which to start the configuration page
+ * @param widgetId The ID of the widget
+ * @param requestCode The request code
+ */
+ public void startConfigActivity(@NonNull BaseDraggingActivity activity, int widgetId,
+ int requestCode) {
+ mWidgetHost.startConfigActivity(activity, widgetId, requestCode);
+ }
+
+ /**
+ * Starts the binding flow for the widget
+ * @param activity The activity for which to bind the widget
+ * @param appWidgetId The ID of the widget
+ * @param info The {@link AppWidgetProviderInfo} of the widget
+ * @param requestCode The request code
+ */
+ public void startBindFlow(@NonNull BaseActivity activity,
+ int appWidgetId, @NonNull AppWidgetProviderInfo info, int requestCode) {
+ mWidgetHost.startBindFlow(activity, appWidgetId, info, requestCode);
+ }
+
+ /**
+ * Stop the host from listening to the widget updates
+ */
+ public void stopListening() {
+ mWidgetHost.stopListening();
+ }
+
+ /**
+ * Create a view for the specified app widget
+ * @param context The activity context for which the view is created
+ * @param appWidgetId The ID of the widget
+ * @param info The {@link LauncherAppWidgetProviderInfo} of the widget
+ * @return A view for the widget
+ */
+ @NonNull
+ public AppWidgetHostView createView(@NonNull Context context, int appWidgetId,
+ @NonNull LauncherAppWidgetProviderInfo info) {
+ return mWidgetHost.createView(context, appWidgetId, info);
+ }
+
+ /**
+ * Set the interaction handler for the widget host
+ * @param handler The interaction handler
+ */
+ public void setInteractionHandler(
+ @Nullable LauncherAppWidgetHost.LauncherWidgetInteractionHandler handler) {
+ ApiWrapper.setHostInteractionHandler(mWidgetHost, handler);
+ }
+
+ /**
+ * Clears all the views from the host
+ */
+ public void clearViews() {
+ mWidgetHost.clearViews();
+ }
+}
diff --git a/src/com/android/launcher3/SecondaryDropTarget.java b/src/com/android/launcher3/SecondaryDropTarget.java
index 0ee7aae..791cfff 100644
--- a/src/com/android/launcher3/SecondaryDropTarget.java
+++ b/src/com/android/launcher3/SecondaryDropTarget.java
@@ -288,7 +288,7 @@
if (widgetId != INVALID_APPWIDGET_ID) {
mLauncher.setWaitingForResult(
PendingRequestArgs.forWidgetInfo(widgetId, null, info));
- mLauncher.getAppWidgetHost().startConfigActivity(mLauncher, widgetId,
+ mLauncher.getAppWidgetHolder().startConfigActivity(mLauncher, widgetId,
REQUEST_RECONFIGURE_APPWIDGET);
}
return null;
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index fe8b364..f834cce 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -109,7 +109,6 @@
import com.android.launcher3.util.RunnableList;
import com.android.launcher3.util.Thunk;
import com.android.launcher3.util.WallpaperOffsetInterpolator;
-import com.android.launcher3.widget.LauncherAppWidgetHost;
import com.android.launcher3.widget.LauncherAppWidgetHost.ProviderChangedListener;
import com.android.launcher3.widget.LauncherAppWidgetHostView;
import com.android.launcher3.widget.NavigableAppWidgetHostView;
@@ -3391,7 +3390,7 @@
public void widgetsRestored(final ArrayList<LauncherAppWidgetInfo> changedInfo) {
if (!changedInfo.isEmpty()) {
DeferredWidgetRefresh widgetRefresh = new DeferredWidgetRefresh(changedInfo,
- mLauncher.getAppWidgetHost());
+ mLauncher.getAppWidgetHolder());
LauncherAppWidgetInfo item = changedInfo.get(0);
final AppWidgetProviderInfo widgetInfo;
@@ -3517,19 +3516,19 @@
*/
private class DeferredWidgetRefresh implements Runnable, ProviderChangedListener {
private final ArrayList<LauncherAppWidgetInfo> mInfos;
- private final LauncherAppWidgetHost mHost;
+ private final LauncherWidgetHolder mWidgetHolder;
private final Handler mHandler;
private boolean mRefreshPending;
DeferredWidgetRefresh(ArrayList<LauncherAppWidgetInfo> infos,
- LauncherAppWidgetHost host) {
+ LauncherWidgetHolder holder) {
mInfos = infos;
- mHost = host;
+ mWidgetHolder = holder;
mHandler = mLauncher.mHandler;
mRefreshPending = true;
- mHost.addProviderChangeListener(this);
+ mWidgetHolder.addProviderChangeListener(this);
// Force refresh after 10 seconds, if we don't get the provider changed event.
// This could happen when the provider is no longer available in the app.
Message msg = Message.obtain(mHandler, this);
@@ -3539,7 +3538,7 @@
@Override
public void run() {
- mHost.removeProviderChangeListener(this);
+ mWidgetHolder.removeProviderChangeListener(this);
mHandler.removeCallbacks(this);
if (!mRefreshPending) {
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index 2682051..fa2c6e9 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -76,6 +76,8 @@
}
};
+ private static final float ALL_APPS_PULL_BACK_TRANSLATION_DEFAULT = 0f;
+
public static final FloatProperty<AllAppsTransitionController> ALL_APPS_PULL_BACK_TRANSLATION =
new FloatProperty<AllAppsTransitionController>("allAppsPullBackTranslation") {
@@ -92,12 +94,18 @@
public void setValue(AllAppsTransitionController controller, float translation) {
if (controller.mIsTablet) {
controller.mAppsView.getActiveRecyclerView().setTranslationY(translation);
+ controller.getAppsViewPullbackTranslationY().setValue(
+ ALL_APPS_PULL_BACK_TRANSLATION_DEFAULT);
} else {
controller.getAppsViewPullbackTranslationY().setValue(translation);
+ controller.mAppsView.getActiveRecyclerView().setTranslationY(
+ ALL_APPS_PULL_BACK_TRANSLATION_DEFAULT);
}
}
};
+ private static final float ALL_APPS_PULL_BACK_ALPHA_DEFAULT = 1f;
+
public static final FloatProperty<AllAppsTransitionController> ALL_APPS_PULL_BACK_ALPHA =
new FloatProperty<AllAppsTransitionController>("allAppsPullBackAlpha") {
@@ -114,8 +122,12 @@
public void setValue(AllAppsTransitionController controller, float alpha) {
if (controller.mIsTablet) {
controller.mAppsView.getActiveRecyclerView().setAlpha(alpha);
+ controller.getAppsViewPullbackAlpha().setValue(
+ ALL_APPS_PULL_BACK_ALPHA_DEFAULT);
} else {
controller.getAppsViewPullbackAlpha().setValue(alpha);
+ controller.mAppsView.getActiveRecyclerView().setAlpha(
+ ALL_APPS_PULL_BACK_ALPHA_DEFAULT);
}
}
};
@@ -232,8 +244,8 @@
builder.addEndListener(success -> {
// Reset pull back progress and alpha after switching states.
- ALL_APPS_PULL_BACK_TRANSLATION.set(this, 0f);
- ALL_APPS_PULL_BACK_ALPHA.set(this, 1f);
+ ALL_APPS_PULL_BACK_TRANSLATION.set(this, ALL_APPS_PULL_BACK_TRANSLATION_DEFAULT);
+ ALL_APPS_PULL_BACK_ALPHA.set(this, ALL_APPS_PULL_BACK_ALPHA_DEFAULT);
// We only want to close the keyboard if the animation has completed successfully.
// The reason is that with keyboard sync, if the user swipes down from All Apps with
diff --git a/src/com/android/launcher3/allapps/SearchUiManager.java b/src/com/android/launcher3/allapps/SearchUiManager.java
index 6138bc4..228b02b 100644
--- a/src/com/android/launcher3/allapps/SearchUiManager.java
+++ b/src/com/android/launcher3/allapps/SearchUiManager.java
@@ -64,7 +64,8 @@
/**
* sets highlight result's title
*/
- default void setFocusedResultTitle(@Nullable CharSequence title) { }
+ default void setFocusedResultTitle(
+ @Nullable CharSequence title, @Nullable CharSequence subtitle) {}
/** Refresh the currently displayed list of results. */
default void refreshResults() {}
diff --git a/src/com/android/launcher3/model/ModelWriter.java b/src/com/android/launcher3/model/ModelWriter.java
index 0a68d4a..514e7b2 100644
--- a/src/com/android/launcher3/model/ModelWriter.java
+++ b/src/com/android/launcher3/model/ModelWriter.java
@@ -36,6 +36,7 @@
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.LauncherSettings.Settings;
+import com.android.launcher3.LauncherWidgetHolder;
import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.logging.FileLog;
@@ -48,7 +49,6 @@
import com.android.launcher3.util.Executors;
import com.android.launcher3.util.ItemInfoMatcher;
import com.android.launcher3.util.LooperExecutor;
-import com.android.launcher3.widget.LauncherAppWidgetHost;
import java.util.ArrayList;
import java.util.Arrays;
@@ -333,13 +333,13 @@
/**
* Deletes the widget info and the widget id.
*/
- public void deleteWidgetInfo(final LauncherAppWidgetInfo info, LauncherAppWidgetHost host,
+ public void deleteWidgetInfo(final LauncherAppWidgetInfo info, LauncherWidgetHolder holder,
@Nullable final String reason) {
notifyDelete(Collections.singleton(info));
- if (host != null && !info.isCustomWidget() && info.isWidgetIdAllocated()) {
+ if (holder != null && !info.isCustomWidget() && info.isWidgetIdAllocated()) {
// Deleting an app widget ID is a void call but writes to disk before returning
// to the caller...
- enqueueDeleteRunnable(() -> host.deleteAppWidgetId(info.appWidgetId));
+ enqueueDeleteRunnable(() -> holder.deleteAppWidgetId(info.appWidgetId));
}
deleteItemFromDatabase(info, reason);
}
diff --git a/src/com/android/launcher3/util/ScrollableLayoutManager.java b/src/com/android/launcher3/util/ScrollableLayoutManager.java
index 17eaefd..9bc4ddc 100644
--- a/src/com/android/launcher3/util/ScrollableLayoutManager.java
+++ b/src/com/android/launcher3/util/ScrollableLayoutManager.java
@@ -44,8 +44,6 @@
* whereas widgets will have strictly increasing values
* sample values: 0, 10, 50, 60, 110
*/
-
- //
private int[] mTotalHeightCache = new int[1];
private int mLastValidHeightIndex = 0;
@@ -62,16 +60,23 @@
@Override
public void layoutDecorated(@NonNull View child, int left, int top, int right, int bottom) {
super.layoutDecorated(child, left, top, right, bottom);
- mCachedSizes.put(
- mRv.getChildViewHolder(child).getItemViewType(), child.getMeasuredHeight());
+ updateCachedSize(child);
}
@Override
public void layoutDecoratedWithMargins(@NonNull View child, int left, int top, int right,
int bottom) {
super.layoutDecoratedWithMargins(child, left, top, right, bottom);
- mCachedSizes.put(
- mRv.getChildViewHolder(child).getItemViewType(), child.getMeasuredHeight());
+ updateCachedSize(child);
+ }
+
+ private void updateCachedSize(@NonNull View child) {
+ int viewType = mRv.getChildViewHolder(child).getItemViewType();
+ int size = child.getMeasuredHeight();
+ if (mCachedSizes.get(viewType, -1) != size) {
+ invalidateScrollCache();
+ }
+ mCachedSizes.put(viewType, size);
}
@Override
diff --git a/src/com/android/launcher3/widget/WidgetAddFlowHandler.java b/src/com/android/launcher3/widget/WidgetAddFlowHandler.java
index 9313266..9319a9c 100644
--- a/src/com/android/launcher3/widget/WidgetAddFlowHandler.java
+++ b/src/com/android/launcher3/widget/WidgetAddFlowHandler.java
@@ -55,7 +55,7 @@
public void startBindFlow(Launcher launcher, int appWidgetId, ItemInfo info, int requestCode) {
launcher.setWaitingForResult(PendingRequestArgs.forWidgetInfo(appWidgetId, this, info));
- launcher.getAppWidgetHost()
+ launcher.getAppWidgetHolder()
.startBindFlow(launcher, appWidgetId, mProviderInfo, requestCode);
}
@@ -77,7 +77,7 @@
return false;
}
launcher.setWaitingForResult(PendingRequestArgs.forWidgetInfo(appWidgetId, this, info));
- launcher.getAppWidgetHost().startConfigActivity(launcher, appWidgetId, requestCode);
+ launcher.getAppWidgetHolder().startConfigActivity(launcher, appWidgetId, requestCode);
return true;
}
diff --git a/src/com/android/launcher3/widget/WidgetHostViewLoader.java b/src/com/android/launcher3/widget/WidgetHostViewLoader.java
index 46141e0..b18cd47 100644
--- a/src/com/android/launcher3/widget/WidgetHostViewLoader.java
+++ b/src/com/android/launcher3/widget/WidgetHostViewLoader.java
@@ -59,7 +59,7 @@
// Cleanup widget id
if (mWidgetLoadingId != -1) {
- mLauncher.getAppWidgetHost().deleteAppWidgetId(mWidgetLoadingId);
+ mLauncher.getAppWidgetHolder().deleteAppWidgetId(mWidgetLoadingId);
mWidgetLoadingId = -1;
}
@@ -69,7 +69,7 @@
Log.d(TAG, "...removing widget from drag layer");
}
mLauncher.getDragLayer().removeView(mInfo.boundWidget);
- mLauncher.getAppWidgetHost().deleteAppWidgetId(mInfo.boundWidget.getAppWidgetId());
+ mLauncher.getAppWidgetHolder().deleteAppWidgetId(mInfo.boundWidget.getAppWidgetId());
mInfo.boundWidget = null;
}
}
@@ -94,7 +94,7 @@
mBindWidgetRunnable = new Runnable() {
@Override
public void run() {
- mWidgetLoadingId = mLauncher.getAppWidgetHost().allocateAppWidgetId();
+ mWidgetLoadingId = mLauncher.getAppWidgetHolder().allocateAppWidgetId();
if (LOGD) {
Log.d(TAG, "Binding widget, id: " + mWidgetLoadingId);
}
@@ -116,7 +116,7 @@
if (mWidgetLoadingId == -1) {
return;
}
- AppWidgetHostView hostView = mLauncher.getAppWidgetHost().createView(
+ AppWidgetHostView hostView = mLauncher.getAppWidgetHolder().createView(
(Context) mLauncher, mWidgetLoadingId, pInfo);
mInfo.boundWidget = hostView;
diff --git a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
index da8e25c..21b2647 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
@@ -321,7 +321,7 @@
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
- mActivityContext.getAppWidgetHost().addProviderChangeListener(this);
+ mActivityContext.getAppWidgetHolder().addProviderChangeListener(this);
notifyWidgetProvidersChanged();
onRecommendedWidgetsBound();
}
@@ -329,7 +329,7 @@
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
- mActivityContext.getAppWidgetHost().removeProviderChangeListener(this);
+ mActivityContext.getAppWidgetHolder().removeProviderChangeListener(this);
mAdapters.get(AdapterHolder.PRIMARY).mWidgetsRecyclerView
.removeOnAttachStateChangeListener(mBindScrollbarInSearchMode);
if (mHasWorkProfile) {
diff --git a/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java
index fa39ce0..0f861eb 100644
--- a/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java
@@ -190,7 +190,7 @@
waitForLauncherCondition("App widget options did not update",
l -> appWidgetManager.getAppWidgetOptions(appWidgetId).getBoolean(
WidgetManagerHelper.WIDGET_OPTION_RESTORE_COMPLETED));
- executeOnLauncher(l -> l.getAppWidgetHost().startListening());
+ executeOnLauncher(l -> l.getAppWidgetHolder().startListening());
verifyWidgetPresent(info);
assertNull(mLauncher.getWorkspace().tryGetPendingWidget(100));
}