summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
Diffstat (limited to 'libs')
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/TaskView.java6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java41
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java70
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerImeController.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerView.java2
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TaskViewTest.java4
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java23
-rw-r--r--libs/hwui/jni/Typeface.cpp25
10 files changed, 127 insertions, 56 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/TaskView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/TaskView.java
index 59a765d49a14..7440f19a6e7c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/TaskView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/TaskView.java
@@ -87,16 +87,12 @@ public class TaskView extends SurfaceView implements SurfaceHolder.Callback,
super(context, null, 0, 0, true /* disableBackgroundLayer */);
mTaskOrganizer = organizer;
+ mExecutor = organizer.getExecutor();
setUseAlpha();
getHolder().addCallback(this);
mGuard.open("release");
}
- // TODO: Use TaskOrganizer executor when part of wmshell proper
- public void setExecutor(Executor executor) {
- mExecutor = executor;
- }
-
/**
* Only one listener may be set on the view, throws an exception otherwise.
*/
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
index 318a0bd42940..4bf01f7cffac 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
@@ -59,7 +59,6 @@ import com.android.internal.policy.ScreenDecorationsUtils;
import com.android.wm.shell.R;
import com.android.wm.shell.TaskView;
import com.android.wm.shell.common.AlphaOptimizedButton;
-import com.android.wm.shell.common.HandlerExecutor;
import com.android.wm.shell.common.TriangleShape;
import java.io.FileDescriptor;
@@ -304,11 +303,6 @@ public class BubbleExpandedView extends LinearLayout {
setLayoutDirection(LAYOUT_DIRECTION_LOCALE);
}
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
- mTaskView.setExecutor(new HandlerExecutor(getHandler()));
- }
/**
* Initialize {@link BubbleController} and {@link BubbleStackView} here, this method must need
* to be called after view inflate.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
index 50d9fe8629ac..e97fe0a9111c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
@@ -112,7 +112,7 @@ public class DividerView extends FrameLayout implements View.OnTouchListener {
}
if (mMoving) {
final int position = mSplitLayout.getDividePosition() + touchPos - mStartPos;
- mSplitLayout.updateDividePosition(position);
+ mSplitLayout.updateDivideBounds(position);
}
break;
case MotionEvent.ACTION_UP:
@@ -131,7 +131,7 @@ public class DividerView extends FrameLayout implements View.OnTouchListener {
final int position = mSplitLayout.getDividePosition() + touchPos - mStartPos;
final DividerSnapAlgorithm.SnapTarget snapTarget =
mSplitLayout.findSnapTarget(position, velocity);
- mSplitLayout.setSnapTarget(snapTarget);
+ mSplitLayout.snapToTarget(position, snapTarget);
break;
}
return true;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
index e11037f55cfa..4c70b5d32108 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
@@ -22,6 +22,9 @@ import static android.view.WindowManager.DOCKED_TOP;
import static com.android.internal.policy.DividerSnapAlgorithm.SnapTarget.FLAG_DISMISS_END;
import static com.android.internal.policy.DividerSnapAlgorithm.SnapTarget.FLAG_DISMISS_START;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
@@ -31,6 +34,7 @@ import android.view.SurfaceControl;
import androidx.annotation.Nullable;
import com.android.internal.policy.DividerSnapAlgorithm;
+import com.android.wm.shell.animation.Interpolators;
/**
* Records and handles layout of splits. Helps to calculate proper bounds when configuration or
@@ -145,17 +149,23 @@ public class SplitLayout {
* Updates bounds with the passing position. Usually used to update recording bounds while
* performing animation or dragging divider bar to resize the splits.
*/
- public void updateDividePosition(int position) {
+ void updateDivideBounds(int position) {
updateBounds(position);
mLayoutChangeListener.onBoundsChanging(this);
}
+ void setDividePosition(int position) {
+ mDividePosition = position;
+ updateBounds(mDividePosition);
+ mLayoutChangeListener.onBoundsChanged(this);
+ }
+
/**
* Sets new divide position and updates bounds correspondingly. Notifies listener if the new
* target indicates dismissing split.
*/
- public void setSnapTarget(DividerSnapAlgorithm.SnapTarget snapTarget) {
- switch(snapTarget.flag) {
+ public void snapToTarget(int currentPosition, DividerSnapAlgorithm.SnapTarget snapTarget) {
+ switch (snapTarget.flag) {
case FLAG_DISMISS_START:
mLayoutChangeListener.onSnappedToDismiss(false /* snappedToEnd */);
break;
@@ -163,9 +173,7 @@ public class SplitLayout {
mLayoutChangeListener.onSnappedToDismiss(true /* snappedToEnd */);
break;
default:
- mDividePosition = snapTarget.position;
- updateBounds(mDividePosition);
- mLayoutChangeListener.onBoundsChanged(this);
+ flingDividePosition(currentPosition, snapTarget.position);
break;
}
}
@@ -189,6 +197,27 @@ public class SplitLayout {
isLandscape ? DOCKED_LEFT : DOCKED_TOP /* dockSide */);
}
+ private void flingDividePosition(int from, int to) {
+ ValueAnimator animator = ValueAnimator
+ .ofInt(from, to)
+ .setDuration(250);
+ animator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
+ animator.addUpdateListener(
+ animation -> updateDivideBounds((int) animation.getAnimatedValue()));
+ animator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ setDividePosition(to);
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ setDividePosition(to);
+ }
+ });
+ animator.start();
+ }
+
private static boolean isLandscape(Rect bounds) {
return bounds.width() > bounds.height();
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java
index d65ad62cdbbb..a944e3bc50cf 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java
@@ -63,6 +63,16 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback {
private String mStartOneHandedDescription;
private String mStopOneHandedDescription;
+ private enum ONE_HANDED_TRIGGER_STATE {
+ UNSET, ENTERING, EXITING
+ }
+ /**
+ * Current One-Handed trigger state.
+ * Note: This is a dynamic state, whenever last state has been confirmed
+ * (i.e. onStartFinished() or onStopFinished()), the state should be set "UNSET" at final.
+ */
+ private ONE_HANDED_TRIGGER_STATE mTriggerState = ONE_HANDED_TRIGGER_STATE.UNSET;
+
/**
* Container of the tutorial panel showing at outside region when one handed starting
*/
@@ -74,6 +84,21 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback {
public void onTutorialAnimationUpdate(int offset) {
mUpdateHandler.post(() -> onAnimationUpdate(offset));
}
+
+ @Override
+ public void onOneHandedAnimationStart(
+ OneHandedAnimationController.OneHandedTransitionAnimator animator) {
+ mUpdateHandler.post(() -> {
+ final Rect startValue = (Rect) animator.getStartValue();
+ if (mTriggerState == ONE_HANDED_TRIGGER_STATE.UNSET) {
+ mTriggerState = (startValue.top == 0)
+ ? ONE_HANDED_TRIGGER_STATE.ENTERING : ONE_HANDED_TRIGGER_STATE.EXITING;
+ if (mCanShowTutorial && mTriggerState == ONE_HANDED_TRIGGER_STATE.ENTERING) {
+ createTutorialTarget();
+ }
+ }
+ });
+ }
};
public OneHandedTutorialHandler(Context context) {
@@ -100,9 +125,6 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback {
R.string.accessibility_action_start_one_handed);
mStopOneHandedDescription = context.getResources().getString(
R.string.accessibility_action_stop_one_handed);
- if (mCanShowTutorial) {
- createOrUpdateTutorialTarget();
- }
}
@Override
@@ -111,6 +133,7 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback {
updateFinished(View.VISIBLE, 0f);
updateTutorialCount();
announcementForScreenReader(true);
+ mTriggerState = ONE_HANDED_TRIGGER_STATE.UNSET;
});
}
@@ -119,6 +142,8 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback {
mUpdateHandler.post(() -> {
updateFinished(View.INVISIBLE, -mTargetViewContainer.getHeight());
announcementForScreenReader(false);
+ removeTutorialFromWindowManager();
+ mTriggerState = ONE_HANDED_TRIGGER_STATE.UNSET;
});
}
@@ -126,7 +151,6 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback {
if (!canShowTutorial()) {
return;
}
-
mTargetViewContainer.setVisibility(visible);
mTargetViewContainer.setTranslationY(finalPosition);
}
@@ -155,24 +179,23 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback {
* Adds the tutorial target view to the WindowManager and update its layout, so it's ready
* to be animated in.
*/
- private void createOrUpdateTutorialTarget() {
- mUpdateHandler.post(() -> {
- if (!mTargetViewContainer.isAttachedToWindow()) {
- mTargetViewContainer.setVisibility(View.INVISIBLE);
-
- try {
- mWindowManager.addView(mTargetViewContainer, getTutorialTargetLayoutParams());
- } catch (IllegalStateException e) {
- // This shouldn't happen, but if the target is already added, just update its
- // layout params.
- mWindowManager.updateViewLayout(
- mTargetViewContainer, getTutorialTargetLayoutParams());
- }
- } else {
- mWindowManager.updateViewLayout(mTargetViewContainer,
- getTutorialTargetLayoutParams());
+ private void createTutorialTarget() {
+ if (!mTargetViewContainer.isAttachedToWindow()) {
+ try {
+ mWindowManager.addView(mTargetViewContainer, getTutorialTargetLayoutParams());
+ } catch (IllegalStateException e) {
+ // This shouldn't happen, but if the target is already added, just update its
+ // layout params.
+ mWindowManager.updateViewLayout(
+ mTargetViewContainer, getTutorialTargetLayoutParams());
}
- });
+ }
+ }
+
+ private void removeTutorialFromWindowManager() {
+ if (mTargetViewContainer.isAttachedToWindow()) {
+ mWindowManager.removeViewImmediate(mTargetViewContainer);
+ }
}
OneHandedAnimationCallback getAnimationCallback() {
@@ -193,7 +216,6 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback {
lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
lp.setFitInsetsTypes(0 /* types */);
lp.setTitle("one-handed-tutorial-overlay");
-
return lp;
}
@@ -206,10 +228,12 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback {
private boolean canShowTutorial() {
if (!mCanShowTutorial) {
+ // Since canSHowTutorial() will be called in onAnimationUpdate() and we still need to
+ // hide Tutorial text in the period of continuously onAnimationUpdate() API call,
+ // so we have to hide mTargetViewContainer here.
mTargetViewContainer.setVisibility(View.GONE);
return false;
}
-
return true;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerImeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerImeController.java
index eb82357f2dea..71710af4ffb5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerImeController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerImeController.java
@@ -26,6 +26,7 @@ import android.annotation.Nullable;
import android.graphics.Rect;
import android.os.Handler;
import android.util.Slog;
+import android.view.Choreographer;
import android.view.SurfaceControl;
import android.window.TaskOrganizer;
import android.window.WindowContainerToken;
@@ -338,6 +339,7 @@ class DividerImeController implements DisplayImeController.ImePositionProcessor
SurfaceControl.Transaction t = mTransactionPool.acquire();
float value = (float) animation.getAnimatedValue();
onProgress(value, t);
+ t.setFrameTimelineVsync(Choreographer.getSfInstance().getVsyncId());
t.apply();
mTransactionPool.release(t);
});
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerView.java
index c6496ad6246f..ba071666b5aa 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerView.java
@@ -37,6 +37,7 @@ import android.os.Handler;
import android.os.RemoteException;
import android.util.AttributeSet;
import android.util.Slog;
+import android.view.Choreographer;
import android.view.Display;
import android.view.MotionEvent;
import android.view.PointerIcon;
@@ -1108,6 +1109,7 @@ public class DividerView extends FrameLayout implements OnTouchListener,
}
resizeSplitSurfaces(t, mDockedRect, mDockedTaskRect, mOtherRect, mOtherTaskRect);
if (ownTransaction) {
+ t.setFrameTimelineVsync(Choreographer.getSfInstance().getVsyncId());
t.apply();
mTiles.releaseTransaction(t);
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TaskViewTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TaskViewTest.java
index 34f772faf9a9..11bf4ff2fd35 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TaskViewTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TaskViewTest.java
@@ -30,6 +30,7 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.app.ActivityManager;
import android.app.ActivityOptions;
@@ -96,8 +97,8 @@ public class TaskViewTest extends ShellTestCase {
return null;
}).when(mExecutor).execute(any());
+ when(mOrganizer.getExecutor()).thenReturn(mExecutor);
mTaskView = new TaskView(mContext, mOrganizer);
- mTaskView.setExecutor(mExecutor);
mTaskView.setListener(mViewListener);
}
@@ -111,7 +112,6 @@ public class TaskViewTest extends ShellTestCase {
@Test
public void testSetPendingListener_throwsException() {
TaskView taskView = new TaskView(mContext, mOrganizer);
- mTaskView.setExecutor(mExecutor);
taskView.setListener(mViewListener);
try {
taskView.setListener(mViewListener);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java
index d87f4c60fad4..9fdd59bee176 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java
@@ -69,24 +69,27 @@ public class SplitLayoutTests extends ShellTestCase {
}
@Test
- public void testUpdateDividePosition() {
- mSplitLayout.updateDividePosition(anyInt());
+ public void testUpdateDivideBounds() {
+ mSplitLayout.updateDivideBounds(anyInt());
verify(mLayoutChangeListener).onBoundsChanging(any(SplitLayout.class));
}
@Test
- public void testSetSnapTarget() {
- DividerSnapAlgorithm.SnapTarget snapTarget = getSnapTarget(0,
+ @UiThreadTest
+ public void testSnapToTarget() {
+ DividerSnapAlgorithm.SnapTarget snapTarget = getSnapTarget(0 /* position */,
DividerSnapAlgorithm.SnapTarget.FLAG_NONE);
- mSplitLayout.setSnapTarget(snapTarget);
- verify(mLayoutChangeListener).onBoundsChanged(any(SplitLayout.class));
+ mSplitLayout.snapToTarget(0 /* currentPosition */, snapTarget);
+ verify(mLayoutChangeListener).onBoundsChanging(any(SplitLayout.class));
// verify it callbacks properly when the snap target indicates dismissing split.
- snapTarget = getSnapTarget(0, DividerSnapAlgorithm.SnapTarget.FLAG_DISMISS_START);
- mSplitLayout.setSnapTarget(snapTarget);
+ snapTarget = getSnapTarget(0 /* position */,
+ DividerSnapAlgorithm.SnapTarget.FLAG_DISMISS_START);
+ mSplitLayout.snapToTarget(0 /* currentPosition */, snapTarget);
verify(mLayoutChangeListener).onSnappedToDismiss(eq(false));
- snapTarget = getSnapTarget(0, DividerSnapAlgorithm.SnapTarget.FLAG_DISMISS_END);
- mSplitLayout.setSnapTarget(snapTarget);
+ snapTarget = getSnapTarget(0 /* position */,
+ DividerSnapAlgorithm.SnapTarget.FLAG_DISMISS_END);
+ mSplitLayout.snapToTarget(0 /* currentPosition */, snapTarget);
verify(mLayoutChangeListener).onSnappedToDismiss(eq(true));
}
diff --git a/libs/hwui/jni/Typeface.cpp b/libs/hwui/jni/Typeface.cpp
index a2964d6627a1..10c80774fd16 100644
--- a/libs/hwui/jni/Typeface.cpp
+++ b/libs/hwui/jni/Typeface.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#define ATRACE_TAG ATRACE_TAG_VIEW
#include "FontUtils.h"
#include "GraphicsJNI.h"
#include "fonts/Font.h"
@@ -25,8 +26,13 @@
#include <minikin/FontCollection.h>
#include <minikin/FontFamily.h>
#include <minikin/SystemFonts.h>
+#include <utils/TraceUtils.h>
+
+#include <mutex>
+#include <unordered_map>
using namespace android;
+using android::uirenderer::TraceUtils;
static inline Typeface* toTypeface(jlong ptr) {
return reinterpret_cast<Typeface*>(ptr);
@@ -149,6 +155,20 @@ static void Typeface_registerGenericFamily(JNIEnv *env, jobject, jstring familyN
toTypeface(ptr)->fFontCollection);
}
+static sk_sp<SkData> makeSkDataCached(const std::string& path) {
+ // We don't clear cache as Typeface objects created by Typeface_readTypefaces() will be stored
+ // in a static field and will not be garbage collected.
+ static std::unordered_map<std::string, sk_sp<SkData>> cache;
+ static std::mutex mutex;
+ ALOG_ASSERT(!path.empty());
+ std::lock_guard lock{mutex};
+ sk_sp<SkData>& entry = cache[path];
+ if (entry.get() == nullptr) {
+ entry = SkData::MakeFromFileName(path.c_str());
+ }
+ return entry;
+}
+
static std::function<std::shared_ptr<minikin::MinikinFont>()> readMinikinFontSkia(
minikin::BufferReader* reader) {
std::string_view fontPath = reader->readString();
@@ -158,8 +178,9 @@ static std::function<std::shared_ptr<minikin::MinikinFont>()> readMinikinFontSki
std::tie(axesPtr, axesCount) = reader->readArray<minikin::FontVariation>();
return [fontPath, fontIndex, axesPtr, axesCount]() -> std::shared_ptr<minikin::MinikinFont> {
std::string path(fontPath.data(), fontPath.size());
- sk_sp<SkData> data = SkData::MakeFromFileName(path.c_str());
- if (data == nullptr) {
+ ATRACE_FORMAT("Loading font %s", path.c_str());
+ sk_sp<SkData> data = makeSkDataCached(path);
+ if (data.get() == nullptr) {
// This may happen if:
// 1. When the process failed to open the file (e.g. invalid path or permission).
// 2. When the process failed to map the file (e.g. hitting max_map_count limit).