Merge "Add flag for VDM settings" into main
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index a81bcbc..a452226 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -575,14 +575,22 @@
EVENT_FLAG_DISPLAY_ADDED,
EVENT_FLAG_DISPLAY_CHANGED,
EVENT_FLAG_DISPLAY_REMOVED,
- EVENT_FLAG_DISPLAY_BRIGHTNESS,
- EVENT_FLAG_HDR_SDR_RATIO_CHANGED,
- EVENT_FLAG_DISPLAY_CONNECTION_CHANGED,
})
@Retention(RetentionPolicy.SOURCE)
public @interface EventFlag {}
/**
+ * @hide
+ */
+ @LongDef(flag = true, prefix = {"PRIVATE_EVENT_FLAG_"}, value = {
+ PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS,
+ PRIVATE_EVENT_FLAG_HDR_SDR_RATIO_CHANGED,
+ PRIVATE_EVENT_FLAG_DISPLAY_CONNECTION_CHANGED,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface PrivateEventFlag {}
+
+ /**
* Event type for when a new display is added.
*
* @see #registerDisplayListener(DisplayListener, Handler, long)
@@ -618,7 +626,7 @@
*
* @hide
*/
- public static final long EVENT_FLAG_DISPLAY_BRIGHTNESS = 1L << 3;
+ public static final long PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS = 1L << 0;
/**
* Event flag to register for a display's hdr/sdr ratio changes. This notification is sent
@@ -631,14 +639,16 @@
*
* @hide
*/
- public static final long EVENT_FLAG_HDR_SDR_RATIO_CHANGED = 1L << 4;
+ public static final long PRIVATE_EVENT_FLAG_HDR_SDR_RATIO_CHANGED = 1L << 1;
/**
* Event flag to register for a display's connection changed.
*
+ * @see #registerDisplayListener(DisplayListener, Handler, long)
* @hide
*/
- public static final long EVENT_FLAG_DISPLAY_CONNECTION_CHANGED = 1L << 5;
+ public static final long PRIVATE_EVENT_FLAG_DISPLAY_CONNECTION_CHANGED = 1L << 2;
+
/** @hide */
public DisplayManager(Context context) {
@@ -774,20 +784,49 @@
* @param listener The listener to register.
* @param handler The handler on which the listener should be invoked, or null
* if the listener should be invoked on the calling thread's looper.
- * @param eventFlagsMask A bitmask of the event types for which this listener is subscribed.
+ * @param eventFlags A bitmask of the event types for which this listener is subscribed.
*
* @see #EVENT_FLAG_DISPLAY_ADDED
* @see #EVENT_FLAG_DISPLAY_CHANGED
* @see #EVENT_FLAG_DISPLAY_REMOVED
- * @see #EVENT_FLAG_DISPLAY_BRIGHTNESS
* @see #registerDisplayListener(DisplayListener, Handler)
* @see #unregisterDisplayListener
*
* @hide
*/
public void registerDisplayListener(@NonNull DisplayListener listener,
- @Nullable Handler handler, @EventFlag long eventFlagsMask) {
- mGlobal.registerDisplayListener(listener, handler, eventFlagsMask,
+ @Nullable Handler handler, @EventFlag long eventFlags) {
+ mGlobal.registerDisplayListener(listener, handler,
+ mGlobal.mapFlagsToInternalEventFlag(eventFlags, 0),
+ ActivityThread.currentPackageName());
+ }
+
+ /**
+ * Registers a display listener to receive notifications about given display event types.
+ *
+ * @param listener The listener to register.
+ * @param handler The handler on which the listener should be invoked, or null
+ * if the listener should be invoked on the calling thread's looper.
+ * @param eventFlags A bitmask of the event types for which this listener is subscribed.
+ * @param privateEventFlags A bitmask of the private event types for which this listener
+ * is subscribed.
+ *
+ * @see #EVENT_FLAG_DISPLAY_ADDED
+ * @see #EVENT_FLAG_DISPLAY_CHANGED
+ * @see #EVENT_FLAG_DISPLAY_REMOVED
+ * @see #PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS
+ * @see #PRIVATE_EVENT_FLAG_DISPLAY_CONNECTION_CHANGED
+ * @see #PRIVATE_EVENT_FLAG_HDR_SDR_RATIO_CHANGED
+ * @see #registerDisplayListener(DisplayListener, Handler)
+ * @see #unregisterDisplayListener
+ *
+ * @hide
+ */
+ public void registerDisplayListener(@NonNull DisplayListener listener,
+ @Nullable Handler handler, @EventFlag long eventFlags,
+ @PrivateEventFlag long privateEventFlags) {
+ mGlobal.registerDisplayListener(listener, handler,
+ mGlobal.mapFlagsToInternalEventFlag(eventFlags, privateEventFlags),
ActivityThread.currentPackageName());
}
diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java
index 56307ae..644850a 100644
--- a/core/java/android/hardware/display/DisplayManagerGlobal.java
+++ b/core/java/android/hardware/display/DisplayManagerGlobal.java
@@ -24,6 +24,7 @@
import android.annotation.FlaggedApi;
import android.annotation.FloatRange;
import android.annotation.IntDef;
+import android.annotation.LongDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
@@ -118,6 +119,24 @@
public static final int EVENT_DISPLAY_CONNECTED = 6;
public static final int EVENT_DISPLAY_DISCONNECTED = 7;
+ @LongDef(prefix = {"INTERNAL_EVENT_DISPLAY"}, flag = true, value = {
+ INTERNAL_EVENT_FLAG_DISPLAY_ADDED,
+ INTERNAL_EVENT_FLAG_DISPLAY_CHANGED,
+ INTERNAL_EVENT_FLAG_DISPLAY_REMOVED,
+ INTERNAL_EVENT_FLAG_DISPLAY_BRIGHTNESS_CHANGED,
+ INTERNAL_EVENT_FLAG_DISPLAY_HDR_SDR_RATIO_CHANGED,
+ INTERNAL_EVENT_FLAG_DISPLAY_CONNECTION_CHANGED,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface InternalEventFlag {}
+
+ public static final long INTERNAL_EVENT_FLAG_DISPLAY_ADDED = 1L << 0;
+ public static final long INTERNAL_EVENT_FLAG_DISPLAY_CHANGED = 1L << 1;
+ public static final long INTERNAL_EVENT_FLAG_DISPLAY_REMOVED = 1L << 2;
+ public static final long INTERNAL_EVENT_FLAG_DISPLAY_BRIGHTNESS_CHANGED = 1L << 3;
+ public static final long INTERNAL_EVENT_FLAG_DISPLAY_HDR_SDR_RATIO_CHANGED = 1L << 4;
+ public static final long INTERNAL_EVENT_FLAG_DISPLAY_CONNECTION_CHANGED = 1L << 5;
+
@UnsupportedAppUsage
private static DisplayManagerGlobal sInstance;
@@ -130,7 +149,7 @@
private final IDisplayManager mDm;
private DisplayManagerCallback mCallback;
- private @EventFlag long mRegisteredEventFlagsMask = 0;
+ private @InternalEventFlag long mRegisteredInternalEventFlag = 0;
private final CopyOnWriteArrayList<DisplayListenerDelegate> mDisplayListeners =
new CopyOnWriteArrayList<>();
@@ -346,11 +365,11 @@
* @param packageName of the calling package.
*/
public void registerDisplayListener(@NonNull DisplayListener listener,
- @Nullable Handler handler, @EventFlag long eventFlagsMask,
+ @Nullable Handler handler, @InternalEventFlag long internalEventFlagsMask,
String packageName) {
Looper looper = getLooperForHandler(handler);
Handler springBoard = new Handler(looper);
- registerDisplayListener(listener, new HandlerExecutor(springBoard), eventFlagsMask,
+ registerDisplayListener(listener, new HandlerExecutor(springBoard), internalEventFlagsMask,
packageName);
}
@@ -359,32 +378,34 @@
*
* @param listener The listener that will be called when display changes occur.
* @param executor Executor for the thread that will be receiving the callbacks. Cannot be null.
- * @param eventFlagsMask Flag of events to be listened to.
+ * @param internalEventFlagsMask Mask of events to be listened to.
* @param packageName of the calling package.
*/
public void registerDisplayListener(@NonNull DisplayListener listener,
- @NonNull Executor executor, @EventFlag long eventFlagsMask, String packageName) {
+ @NonNull Executor executor, @InternalEventFlag long internalEventFlagsMask,
+ String packageName) {
if (listener == null) {
throw new IllegalArgumentException("listener must not be null");
}
- if (eventFlagsMask == 0) {
+ if (internalEventFlagsMask == 0) {
throw new IllegalArgumentException("The set of events to listen to must not be empty.");
}
if (extraLogging()) {
Slog.i(TAG, "Registering Display Listener: "
- + Long.toBinaryString(eventFlagsMask) + ", packageName: " + packageName);
+ + Long.toBinaryString(internalEventFlagsMask)
+ + ", packageName: " + packageName);
}
synchronized (mLock) {
int index = findDisplayListenerLocked(listener);
if (index < 0) {
mDisplayListeners.add(new DisplayListenerDelegate(listener, executor,
- eventFlagsMask, packageName));
+ internalEventFlagsMask, packageName));
registerCallbackIfNeededLocked();
} else {
- mDisplayListeners.get(index).setEventFlagsMask(eventFlagsMask);
+ mDisplayListeners.get(index).setEventsMask(internalEventFlagsMask);
}
updateCallbackIfNeededLocked();
maybeLogAllDisplayListeners();
@@ -456,17 +477,17 @@
return -1;
}
- @EventFlag
- private int calculateEventFlagsMaskLocked() {
- int mask = 0;
+ @InternalEventFlag
+ private long calculateEventsMaskLocked() {
+ long mask = 0;
final int numListeners = mDisplayListeners.size();
for (int i = 0; i < numListeners; i++) {
- mask |= mDisplayListeners.get(i).mEventFlagsMask;
+ mask |= mDisplayListeners.get(i).mInternalEventFlagsMask;
}
if (mDispatchNativeCallbacks) {
- mask |= DisplayManager.EVENT_FLAG_DISPLAY_ADDED
- | DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
- | DisplayManager.EVENT_FLAG_DISPLAY_REMOVED;
+ mask |= INTERNAL_EVENT_FLAG_DISPLAY_ADDED
+ | INTERNAL_EVENT_FLAG_DISPLAY_CHANGED
+ | INTERNAL_EVENT_FLAG_DISPLAY_REMOVED;
}
return mask;
}
@@ -479,14 +500,14 @@
}
private void updateCallbackIfNeededLocked() {
- int mask = calculateEventFlagsMaskLocked();
+ long mask = calculateEventsMaskLocked();
if (DEBUG) {
- Log.d(TAG, "Flag for listener: " + mask);
+ Log.d(TAG, "Mask for listener: " + mask);
}
- if (mask != mRegisteredEventFlagsMask) {
+ if (mask != mRegisteredInternalEventFlag) {
try {
mDm.registerCallbackWithEventMask(mCallback, mask);
- mRegisteredEventFlagsMask = mask;
+ mRegisteredInternalEventFlag = mask;
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
@@ -1268,8 +1289,8 @@
@Override
public void onDisplayEvent(int displayId, @DisplayEvent int event) {
if (DEBUG) {
- Log.d(TAG, "onDisplayEvent: displayId=" + displayId + ", event=" + eventToString(
- event));
+ Log.d(TAG, "onDisplayEvent: displayId=" + displayId + ", event="
+ + eventToString(event));
}
handleDisplayEvent(displayId, event, false /* forceUpdate */);
}
@@ -1277,7 +1298,7 @@
private static final class DisplayListenerDelegate {
public final DisplayListener mListener;
- public volatile long mEventFlagsMask;
+ public volatile long mInternalEventFlagsMask;
private final DisplayInfo mDisplayInfo = new DisplayInfo();
private final Executor mExecutor;
@@ -1285,10 +1306,10 @@
private final String mPackageName;
DisplayListenerDelegate(DisplayListener listener, @NonNull Executor executor,
- @EventFlag long eventFlag, String packageName) {
+ @InternalEventFlag long internalEventFlag, String packageName) {
mExecutor = executor;
mListener = listener;
- mEventFlagsMask = eventFlag;
+ mInternalEventFlagsMask = internalEventFlag;
mPackageName = packageName;
}
@@ -1310,16 +1331,16 @@
mGenerationId.incrementAndGet();
}
- void setEventFlagsMask(@EventFlag long newEventsFlag) {
- mEventFlagsMask = newEventsFlag;
+ void setEventsMask(@InternalEventFlag long newInternalEventFlagsMask) {
+ mInternalEventFlagsMask = newInternalEventFlagsMask;
}
- private void handleDisplayEventInner(int displayId, @DisplayEvent int eventFlagsMask,
+ private void handleDisplayEventInner(int displayId, @DisplayEvent int event,
@Nullable DisplayInfo info, boolean forceUpdate) {
if (extraLogging()) {
- Slog.i(TAG, "DLD(" + eventToString(eventFlagsMask)
+ Slog.i(TAG, "DLD(" + eventToString(event)
+ ", display=" + displayId
- + ", mEventsFlagMask=" + Long.toBinaryString(mEventFlagsMask)
+ + ", mEventsMask=" + Long.toBinaryString(mInternalEventFlagsMask)
+ ", mPackageName=" + mPackageName
+ ", displayInfo=" + info
+ ", listener=" + mListener.getClass() + ")");
@@ -1327,18 +1348,19 @@
if (DEBUG) {
Trace.beginSection(
TextUtils.trimToSize(
- "DLD(" + eventToString(eventFlagsMask)
+ "DLD(" + eventToString(event)
+ ", display=" + displayId
+ ", listener=" + mListener.getClass() + ")", 127));
}
- switch (eventFlagsMask) {
+ switch (event) {
case EVENT_DISPLAY_ADDED:
- if ((mEventFlagsMask & DisplayManager.EVENT_FLAG_DISPLAY_ADDED) != 0) {
+ if ((mInternalEventFlagsMask & INTERNAL_EVENT_FLAG_DISPLAY_ADDED) != 0) {
mListener.onDisplayAdded(displayId);
}
break;
case EVENT_DISPLAY_CHANGED:
- if ((mEventFlagsMask & DisplayManager.EVENT_FLAG_DISPLAY_CHANGED) != 0) {
+ if ((mInternalEventFlagsMask & INTERNAL_EVENT_FLAG_DISPLAY_CHANGED)
+ != 0) {
if (info != null && (forceUpdate || !info.equals(mDisplayInfo))) {
if (extraLogging()) {
Slog.i(TAG, "Sending onDisplayChanged: Display Changed. Info: "
@@ -1350,29 +1372,32 @@
}
break;
case EVENT_DISPLAY_BRIGHTNESS_CHANGED:
- if ((mEventFlagsMask & DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS) != 0) {
+ if ((mInternalEventFlagsMask
+ & INTERNAL_EVENT_FLAG_DISPLAY_BRIGHTNESS_CHANGED) != 0) {
mListener.onDisplayChanged(displayId);
}
break;
case EVENT_DISPLAY_REMOVED:
- if ((mEventFlagsMask & DisplayManager.EVENT_FLAG_DISPLAY_REMOVED) != 0) {
+ if ((mInternalEventFlagsMask & INTERNAL_EVENT_FLAG_DISPLAY_REMOVED)
+ != 0) {
mListener.onDisplayRemoved(displayId);
}
break;
case EVENT_DISPLAY_HDR_SDR_RATIO_CHANGED:
- if ((mEventFlagsMask & DisplayManager.EVENT_FLAG_HDR_SDR_RATIO_CHANGED) != 0) {
+ if ((mInternalEventFlagsMask
+ & INTERNAL_EVENT_FLAG_DISPLAY_HDR_SDR_RATIO_CHANGED) != 0) {
mListener.onDisplayChanged(displayId);
}
break;
case EVENT_DISPLAY_CONNECTED:
- if ((mEventFlagsMask & DisplayManager.EVENT_FLAG_DISPLAY_CONNECTION_CHANGED)
- != 0) {
+ if ((mInternalEventFlagsMask
+ & INTERNAL_EVENT_FLAG_DISPLAY_CONNECTION_CHANGED) != 0) {
mListener.onDisplayConnected(displayId);
}
break;
case EVENT_DISPLAY_DISCONNECTED:
- if ((mEventFlagsMask & DisplayManager.EVENT_FLAG_DISPLAY_CONNECTION_CHANGED)
- != 0) {
+ if ((mInternalEventFlagsMask
+ & INTERNAL_EVENT_FLAG_DISPLAY_CONNECTION_CHANGED) != 0) {
mListener.onDisplayDisconnected(displayId);
}
break;
@@ -1384,7 +1409,7 @@
@Override
public String toString() {
- return "mEventFlagsMask: {" + mEventFlagsMask + "}, for " + mListener.getClass();
+ return "flag: {" + mInternalEventFlagsMask + "}, for " + mListener.getClass();
}
}
@@ -1532,4 +1557,53 @@
private static boolean extraLogging() {
return sExtraDisplayListenerLogging;
}
+
+
+ /**
+ * Maps the supplied public and private event flags to a unified InternalEventFlag
+ * @param eventFlags A bitmask of the event types for which this listener is subscribed.
+ * @param privateEventFlags A bitmask of the private event types for which this listener
+ * is subscribed.
+ * @return returns the bitmask of both public and private event flags unified to
+ * InternalEventFlag
+ */
+ public @InternalEventFlag long mapFlagsToInternalEventFlag(@EventFlag long eventFlags,
+ @DisplayManager.PrivateEventFlag long privateEventFlags) {
+ return mapPrivateEventFlags(privateEventFlags) | mapPublicEventFlags(eventFlags);
+ }
+
+ private long mapPrivateEventFlags(@DisplayManager.PrivateEventFlag long privateEventFlags) {
+ long baseEventMask = 0;
+ if ((privateEventFlags & DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS) != 0) {
+ baseEventMask |= INTERNAL_EVENT_FLAG_DISPLAY_BRIGHTNESS_CHANGED;
+ }
+
+ if ((privateEventFlags & DisplayManager.PRIVATE_EVENT_FLAG_HDR_SDR_RATIO_CHANGED) != 0) {
+ baseEventMask |= INTERNAL_EVENT_FLAG_DISPLAY_HDR_SDR_RATIO_CHANGED;
+ }
+
+ if ((privateEventFlags
+ & DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_CONNECTION_CHANGED) != 0) {
+ baseEventMask |= INTERNAL_EVENT_FLAG_DISPLAY_CONNECTION_CHANGED;
+ }
+ return baseEventMask;
+ }
+
+ private long mapPublicEventFlags(@EventFlag long eventFlags) {
+ long baseEventMask = 0;
+ if ((eventFlags & DisplayManager.EVENT_FLAG_DISPLAY_ADDED) != 0) {
+ baseEventMask |= INTERNAL_EVENT_FLAG_DISPLAY_ADDED;
+ }
+
+ if ((eventFlags & DisplayManager.EVENT_FLAG_DISPLAY_CHANGED) != 0) {
+ baseEventMask |= INTERNAL_EVENT_FLAG_DISPLAY_CHANGED;
+ }
+
+ if ((eventFlags
+ & DisplayManager.EVENT_FLAG_DISPLAY_REMOVED) != 0) {
+ baseEventMask |= INTERNAL_EVENT_FLAG_DISPLAY_REMOVED;
+ }
+
+ return baseEventMask;
+ }
}
diff --git a/core/java/android/net/vcn/flags.aconfig b/core/java/android/net/vcn/flags.aconfig
index 1adefe5..1b2c575 100644
--- a/core/java/android/net/vcn/flags.aconfig
+++ b/core/java/android/net/vcn/flags.aconfig
@@ -18,13 +18,6 @@
}
flag {
- name: "safe_mode_timeout_config"
- namespace: "vcn"
- description: "Feature flag for adjustable safe mode timeout"
- bug: "317406085"
-}
-
-flag {
name: "fix_config_garbage_collection"
namespace: "vcn"
description: "Handle race condition in subscription change"
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 910e644..0241e94 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -1549,8 +1549,9 @@
// Although we only care about the HDR/SDR ratio changing, that can also come in the
// form of the larger DISPLAY_CHANGED event
mGlobal.registerDisplayListener(toRegister, executor,
- DisplayManager.EVENT_FLAG_HDR_SDR_RATIO_CHANGED
- | DisplayManagerGlobal.EVENT_DISPLAY_CHANGED,
+ DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_CHANGED
+ | DisplayManagerGlobal
+ .INTERNAL_EVENT_FLAG_DISPLAY_HDR_SDR_RATIO_CHANGED,
ActivityThread.currentPackageName());
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 3ce6870..9a2aa0b 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -185,7 +185,6 @@
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.hardware.SyncFence;
-import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManager.DisplayListener;
import android.hardware.display.DisplayManagerGlobal;
import android.hardware.input.InputManagerGlobal;
@@ -1816,9 +1815,9 @@
.registerDisplayListener(
mDisplayListener,
mHandler,
- DisplayManager.EVENT_FLAG_DISPLAY_ADDED
- | DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
- | DisplayManager.EVENT_FLAG_DISPLAY_REMOVED,
+ DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_ADDED
+ | DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_CHANGED
+ | DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_REMOVED,
mBasePackageName);
if (forceInvertColor()) {
diff --git a/core/java/android/window/BackProgressAnimator.java b/core/java/android/window/BackProgressAnimator.java
index a5be58b..16eb437 100644
--- a/core/java/android/window/BackProgressAnimator.java
+++ b/core/java/android/window/BackProgressAnimator.java
@@ -16,8 +16,11 @@
package android.window;
+import static android.window.BackEvent.EDGE_NONE;
+
import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE;
import static com.android.window.flags.Flags.predictiveBackTimestampApi;
+import static com.android.window.flags.Flags.predictiveBackSwipeEdgeNoneApi;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -60,6 +63,12 @@
@Nullable
private Runnable mBackInvokedFinishRunnable;
private FlingAnimation mBackInvokedFlingAnim;
+ private final SpringForce mGestureSpringForce = new SpringForce()
+ .setStiffness(SpringForce.STIFFNESS_MEDIUM)
+ .setDampingRatio(SpringForce.DAMPING_RATIO_NO_BOUNCY);
+ private final SpringForce mButtonSpringForce = new SpringForce()
+ .setStiffness(500)
+ .setDampingRatio(SpringForce.DAMPING_RATIO_NO_BOUNCY);
private final DynamicAnimation.OnAnimationEndListener mOnAnimationEndListener =
(animation, canceled, value, velocity) -> {
if (mBackCancelledFinishRunnable != null) invokeBackCancelledRunnable();
@@ -109,9 +118,7 @@
public BackProgressAnimator() {
mSpring = new SpringAnimation(this, PROGRESS_PROP);
mSpring.addUpdateListener(this);
- mSpring.setSpring(new SpringForce()
- .setStiffness(SpringForce.STIFFNESS_MEDIUM)
- .setDampingRatio(SpringForce.DAMPING_RATIO_NO_BOUNCY));
+ mSpring.setSpring(mGestureSpringForce);
}
/**
@@ -123,6 +130,11 @@
if (!mBackAnimationInProgress) {
return;
}
+ if (predictiveBackSwipeEdgeNoneApi()) {
+ if (event.getSwipeEdge() == EDGE_NONE) {
+ return;
+ }
+ }
mLastBackEvent = event;
if (mSpring == null) {
return;
@@ -143,7 +155,17 @@
mBackAnimationInProgress = true;
updateProgressValue(/* progress */ 0, /* velocity */ 0,
/* frameTime */ System.nanoTime() / TimeUtils.NANOS_PER_MS);
- onBackProgressed(event);
+ if (predictiveBackSwipeEdgeNoneApi()) {
+ if (event.getSwipeEdge() == EDGE_NONE) {
+ mSpring.setSpring(mButtonSpringForce);
+ mSpring.animateToFinalPosition(SCALE_FACTOR);
+ } else {
+ mSpring.setSpring(mGestureSpringForce);
+ onBackProgressed(event);
+ }
+ } else {
+ onBackProgressed(event);
+ }
}
/**
diff --git a/core/java/android/window/flags/windowing_frontend.aconfig b/core/java/android/window/flags/windowing_frontend.aconfig
index 11f6849..9845bf0 100644
--- a/core/java/android/window/flags/windowing_frontend.aconfig
+++ b/core/java/android/window/flags/windowing_frontend.aconfig
@@ -388,4 +388,11 @@
description: "Provide pre-make predictive back API extension"
is_fixed_read_only: true
bug: "362938401"
-}
\ No newline at end of file
+}
+
+flag {
+ name: "predictive_back_three_button_nav"
+ namespace: "systemui"
+ description: "Enable Predictive Back Animation for 3-button-nav"
+ bug: "373544911"
+}
diff --git a/core/java/com/android/internal/display/BrightnessSynchronizer.java b/core/java/com/android/internal/display/BrightnessSynchronizer.java
index 21fbf9d..a50dbb0 100644
--- a/core/java/com/android/internal/display/BrightnessSynchronizer.java
+++ b/core/java/com/android/internal/display/BrightnessSynchronizer.java
@@ -600,8 +600,8 @@
final ContentResolver cr = mContext.getContentResolver();
cr.registerContentObserver(BRIGHTNESS_URI, false,
createBrightnessContentObserver(handler), UserHandle.USER_ALL);
- mDisplayManager.registerDisplayListener(mListener, handler,
- DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS);
+ mDisplayManager.registerDisplayListener(mListener, handler, /* eventFlags */ 0,
+ DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS);
mIsObserving = true;
}
}
diff --git a/core/java/com/android/internal/jank/DisplayResolutionTracker.java b/core/java/com/android/internal/jank/DisplayResolutionTracker.java
index ca6c54d..0c2fd4b 100644
--- a/core/java/com/android/internal/jank/DisplayResolutionTracker.java
+++ b/core/java/com/android/internal/jank/DisplayResolutionTracker.java
@@ -147,8 +147,9 @@
@Override
public void registerDisplayListener(DisplayManager.DisplayListener listener) {
manager.registerDisplayListener(listener, handler,
- DisplayManager.EVENT_FLAG_DISPLAY_ADDED
- | DisplayManager.EVENT_FLAG_DISPLAY_CHANGED,
+ DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_ADDED
+ | DisplayManagerGlobal
+ .INTERNAL_EVENT_FLAG_DISPLAY_CHANGED,
ActivityThread.currentPackageName());
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/CoreDocument.java b/core/java/com/android/internal/widget/remotecompose/core/CoreDocument.java
index 212df02..0761a24 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/CoreDocument.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/CoreDocument.java
@@ -15,12 +15,14 @@
*/
package com.android.internal.widget.remotecompose.core;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
import com.android.internal.widget.remotecompose.core.operations.ComponentValue;
import com.android.internal.widget.remotecompose.core.operations.IntegerExpression;
import com.android.internal.widget.remotecompose.core.operations.NamedVariable;
import com.android.internal.widget.remotecompose.core.operations.RootContentBehavior;
import com.android.internal.widget.remotecompose.core.operations.Theme;
-import com.android.internal.widget.remotecompose.core.operations.layout.ClickModifierEnd;
import com.android.internal.widget.remotecompose.core.operations.layout.ClickModifierOperation;
import com.android.internal.widget.remotecompose.core.operations.layout.Component;
import com.android.internal.widget.remotecompose.core.operations.layout.ComponentEnd;
@@ -28,7 +30,11 @@
import com.android.internal.widget.remotecompose.core.operations.layout.LayoutComponent;
import com.android.internal.widget.remotecompose.core.operations.layout.LoopEnd;
import com.android.internal.widget.remotecompose.core.operations.layout.LoopOperation;
+import com.android.internal.widget.remotecompose.core.operations.layout.OperationsListEnd;
import com.android.internal.widget.remotecompose.core.operations.layout.RootLayoutComponent;
+import com.android.internal.widget.remotecompose.core.operations.layout.TouchCancelModifierOperation;
+import com.android.internal.widget.remotecompose.core.operations.layout.TouchDownModifierOperation;
+import com.android.internal.widget.remotecompose.core.operations.layout.TouchUpModifierOperation;
import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.ComponentModifiers;
import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.ModifierOperation;
import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer;
@@ -49,12 +55,12 @@
ArrayList<Operation> mOperations;
- RootLayoutComponent mRootLayoutComponent = null;
+ @Nullable RootLayoutComponent mRootLayoutComponent = null;
RemoteComposeState mRemoteComposeState = new RemoteComposeState();
- TimeVariables mTimeVariables = new TimeVariables();
+ @NonNull TimeVariables mTimeVariables = new TimeVariables();
// Semantic version of the document
- Version mVersion = new Version(0, 1, 0);
+ @NonNull Version mVersion = new Version(0, 1, 0);
String mContentDescription; // text description of the document (used for accessibility)
@@ -72,6 +78,8 @@
private final HashMap<Long, IntegerExpression> mIntegerExpressions = new HashMap<>();
+ private HashSet<Component> mAppliedTouchOperations = new HashSet<>();
+
private int mLastId = 1; // last component id when inflating the file
public String getContentDescription() {
@@ -272,6 +280,7 @@
*
* @return list of click areas in document coordinates
*/
+ @NonNull
public Set<ClickAreaRepresentation> getClickAreas() {
return mClickAreas;
}
@@ -281,6 +290,7 @@
*
* @return returns the root component if it exists, null otherwise
*/
+ @Nullable
public RootLayoutComponent getRootLayoutComponent() {
return mRootLayoutComponent;
}
@@ -298,6 +308,7 @@
* @param id component id
* @return the component if it exists, null otherwise
*/
+ @Nullable
public Component getComponent(int id) {
if (mRootLayoutComponent != null) {
return mRootLayoutComponent.getComponent(id);
@@ -310,6 +321,7 @@
*
* @return a standardized string representation of the component hierarchy
*/
+ @NonNull
public String displayHierarchy() {
StringSerializer serializer = new StringSerializer();
for (Operation op : mOperations) {
@@ -329,7 +341,8 @@
* @param targetId the id of the value to update with the expression
* @param context the current context
*/
- public void evaluateIntExpression(long expressionId, int targetId, RemoteContext context) {
+ public void evaluateIntExpression(
+ long expressionId, int targetId, @NonNull RemoteContext context) {
IntegerExpression expression = mIntegerExpressions.get(expressionId);
if (expression != null) {
int v = expression.evaluate(context);
@@ -337,22 +350,46 @@
}
}
- /** Callback interface for host actions */
- public interface ActionCallback {
- // TODO: add payload support
- void onAction(String name);
+ // ============== Haptic support ==================
+ public interface HapticEngine {
+ void haptic(int type);
}
- HashSet<ActionCallback> mActionListeners = new HashSet<ActionCallback>();
+ HapticEngine mHapticEngine;
+
+ public void setHapticEngine(HapticEngine engine) {
+ mHapticEngine = engine;
+ }
+
+ public void haptic(int type) {
+ if (mHapticEngine != null) {
+ mHapticEngine.haptic(type);
+ }
+ }
+
+ // ============== Haptic support ==================
+
+ public void appliedTouchOperation(Component operation) {
+ mAppliedTouchOperations.add(operation);
+ }
+
+ /** Callback interface for host actions */
+ public interface ActionCallback {
+ void onAction(String name, Object value);
+ }
+
+ @NonNull HashSet<ActionCallback> mActionListeners = new HashSet<ActionCallback>();
/**
* Warn action listeners for the given named action
*
* @param name the action name
+ * @param value a parameter to the action
*/
- public void runNamedAction(String name) {
+ public void runNamedAction(String name, Object value) {
+ // TODO: we might add an interface to group all valid parameter types
for (ActionCallback callback : mActionListeners) {
- callback.onAction(name);
+ callback.onAction(name, value);
}
}
@@ -374,8 +411,9 @@
void click(int id, String metadata);
}
- HashSet<ClickCallbacks> mClickListeners = new HashSet<>();
- HashSet<ClickAreaRepresentation> mClickAreas = new HashSet<>();
+ @NonNull HashSet<ClickCallbacks> mClickListeners = new HashSet<>();
+ @NonNull HashSet<TouchListener> mTouchListeners = new HashSet<>();
+ @NonNull HashSet<ClickAreaRepresentation> mClickAreas = new HashSet<>();
static class Version {
public final int major;
@@ -456,7 +494,7 @@
}
/** Load operations from the given buffer */
- public void initFromBuffer(RemoteComposeBuffer buffer) {
+ public void initFromBuffer(@NonNull RemoteComposeBuffer buffer) {
mOperations = new ArrayList<Operation>();
buffer.inflateFromBuffer(mOperations);
for (Operation op : mOperations) {
@@ -484,12 +522,16 @@
* @param operations flat list of operations
* @return nested list of operations / components
*/
- private ArrayList<Operation> inflateComponents(ArrayList<Operation> operations) {
+ @NonNull
+ private ArrayList<Operation> inflateComponents(@NonNull ArrayList<Operation> operations) {
Component currentComponent = null;
ArrayList<Component> components = new ArrayList<>();
ArrayList<Operation> finalOperationsList = new ArrayList<>();
ArrayList<Operation> ops = finalOperationsList;
ClickModifierOperation currentClickModifier = null;
+ TouchDownModifierOperation currentTouchDownModifier = null;
+ TouchUpModifierOperation currentTouchUpModifier = null;
+ TouchCancelModifierOperation currentTouchCancelModifier = null;
LoopOperation currentLoop = null;
mLastId = -1;
@@ -519,10 +561,30 @@
// TODO: refactor to add container <- component...
currentClickModifier = (ClickModifierOperation) o;
ops = currentClickModifier.getList();
- } else if (o instanceof ClickModifierEnd) {
+ } else if (o instanceof TouchDownModifierOperation) {
+ currentTouchDownModifier = (TouchDownModifierOperation) o;
+ ops = currentTouchDownModifier.getList();
+ } else if (o instanceof TouchUpModifierOperation) {
+ currentTouchUpModifier = (TouchUpModifierOperation) o;
+ ops = currentTouchUpModifier.getList();
+ } else if (o instanceof TouchCancelModifierOperation) {
+ currentTouchCancelModifier = (TouchCancelModifierOperation) o;
+ ops = currentTouchCancelModifier.getList();
+ } else if (o instanceof OperationsListEnd) {
ops = currentComponent.getList();
- ops.add(currentClickModifier);
- currentClickModifier = null;
+ if (currentClickModifier != null) {
+ ops.add(currentClickModifier);
+ currentClickModifier = null;
+ } else if (currentTouchDownModifier != null) {
+ ops.add(currentTouchDownModifier);
+ currentTouchDownModifier = null;
+ } else if (currentTouchUpModifier != null) {
+ ops.add(currentTouchUpModifier);
+ currentTouchUpModifier = null;
+ } else if (currentTouchCancelModifier != null) {
+ ops.add(currentTouchCancelModifier);
+ currentTouchCancelModifier = null;
+ }
} else if (o instanceof LoopOperation) {
currentLoop = (LoopOperation) o;
ops = currentLoop.getList();
@@ -541,9 +603,9 @@
return ops;
}
- private HashMap<Integer, Component> mComponentMap = new HashMap<Integer, Component>();
+ @NonNull private HashMap<Integer, Component> mComponentMap = new HashMap<Integer, Component>();
- private void registerVariables(RemoteContext context, ArrayList<Operation> list) {
+ private void registerVariables(RemoteContext context, @NonNull ArrayList<Operation> list) {
for (Operation op : list) {
if (op instanceof VariableSupport) {
((VariableSupport) op).updateVariables(context);
@@ -578,7 +640,7 @@
* Called when an initialization is needed, allowing the document to eg load resources / cache
* them.
*/
- public void initializeContext(RemoteContext context) {
+ public void initializeContext(@NonNull RemoteContext context) {
mRemoteComposeState.reset();
mRemoteComposeState.setContext(context);
mClickAreas.clear();
@@ -651,6 +713,15 @@
}
/**
+ * Called by commands to listen to touch events
+ *
+ * @param listener
+ */
+ public void addTouchListener(TouchListener listener) {
+ mTouchListeners.add(listener);
+ }
+
+ /**
* Add a click listener. This will get called when a click is detected on the document
*
* @param callback called when a click area has been hit, passing the click are id and metadata.
@@ -664,6 +735,7 @@
*
* @return set of click listeners
*/
+ @NonNull
public HashSet<CoreDocument.ClickCallbacks> getClickListeners() {
return mClickListeners;
}
@@ -700,12 +772,98 @@
}
/** Warn click listeners when a click area is activated */
- private void warnClickListeners(ClickAreaRepresentation clickArea) {
+ private void warnClickListeners(@NonNull ClickAreaRepresentation clickArea) {
for (ClickCallbacks listener : mClickListeners) {
listener.click(clickArea.mId, clickArea.mMetadata);
}
}
+ /**
+ * Returns true if the document has touch listeners
+ *
+ * @return true if the document needs to react to touch events
+ */
+ public boolean hasTouchListener() {
+ boolean hasComponentsTouchListeners =
+ mRootLayoutComponent != null && mRootLayoutComponent.hasTouchListeners();
+ return hasComponentsTouchListeners || !mTouchListeners.isEmpty();
+ }
+
+ // TODO support velocity estimate support, support regions
+ /**
+ * Support touch drag events on commands supporting touch
+ *
+ * @param x position of touch
+ * @param y position of touch
+ */
+ public boolean touchDrag(RemoteContext context, float x, float y) {
+ context.loadFloat(RemoteContext.ID_TOUCH_POS_X, x);
+ context.loadFloat(RemoteContext.ID_TOUCH_POS_Y, y);
+ for (TouchListener clickArea : mTouchListeners) {
+ clickArea.touchDrag(context, x, y);
+ }
+ if (!mTouchListeners.isEmpty()) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Support touch down events on commands supporting touch
+ *
+ * @param x position of touch
+ * @param y position of touch
+ */
+ public void touchDown(RemoteContext context, float x, float y) {
+ context.loadFloat(RemoteContext.ID_TOUCH_POS_X, x);
+ context.loadFloat(RemoteContext.ID_TOUCH_POS_Y, y);
+ for (TouchListener clickArea : mTouchListeners) {
+ clickArea.touchDown(context, x, y);
+ }
+ if (mRootLayoutComponent != null) {
+ mRootLayoutComponent.onTouchDown(context, this, x, y);
+ }
+ mRepaintNext = 1;
+ }
+
+ /**
+ * Support touch up events on commands supporting touch
+ *
+ * @param x position of touch
+ * @param y position of touch
+ */
+ public void touchUp(RemoteContext context, float x, float y, float dx, float dy) {
+ context.loadFloat(RemoteContext.ID_TOUCH_POS_X, x);
+ context.loadFloat(RemoteContext.ID_TOUCH_POS_Y, y);
+ for (TouchListener clickArea : mTouchListeners) {
+ clickArea.touchUp(context, x, y, dx, dy);
+ }
+ if (mRootLayoutComponent != null) {
+ for (Component component : mAppliedTouchOperations) {
+ component.onTouchUp(context, this, x, y, true);
+ }
+ mAppliedTouchOperations.clear();
+ }
+ mRepaintNext = 1;
+ }
+
+ /**
+ * Support touch cancel events on commands supporting touch
+ *
+ * @param x position of touch
+ * @param y position of touch
+ */
+ public void touchCancel(RemoteContext context, float x, float y, float dx, float dy) {
+ if (mRootLayoutComponent != null) {
+ for (Component component : mAppliedTouchOperations) {
+ component.onTouchCancel(context, this, x, y, true);
+ }
+ mAppliedTouchOperations.clear();
+ }
+ mRepaintNext = 1;
+ }
+
+ @NonNull
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
@@ -721,12 +879,22 @@
*
* @return array of named colors or null
*/
+ @Nullable
public String[] getNamedColors() {
+ return getNamedVariables(NamedVariable.COLOR_TYPE);
+ }
+
+ /**
+ * Gets the names of all named Variables.
+ *
+ * @return array of named variables or null
+ */
+ public String[] getNamedVariables(int type) {
int count = 0;
for (Operation op : mOperations) {
if (op instanceof NamedVariable) {
NamedVariable n = (NamedVariable) op;
- if (n.mVarType == NamedVariable.COLOR_TYPE) {
+ if (n.mVarType == type) {
count++;
}
}
@@ -739,7 +907,7 @@
for (Operation op : mOperations) {
if (op instanceof NamedVariable) {
NamedVariable n = (NamedVariable) op;
- if (n.mVarType == NamedVariable.COLOR_TYPE) {
+ if (n.mVarType == type) {
ret[i++] = n.mVarName;
}
}
@@ -770,10 +938,9 @@
* @param context the provided PaintContext
* @param theme the theme we want to use for this document.
*/
- public void paint(RemoteContext context, int theme) {
+ public void paint(@NonNull RemoteContext context, int theme) {
context.getPaintContext().clearNeedsRepaint();
context.mMode = RemoteContext.ContextMode.UNSET;
-
// current theme starts as UNSPECIFIED, until a Theme setter
// operation gets executed and modify it.
context.setTheme(Theme.UNSPECIFIED);
@@ -807,6 +974,7 @@
}
// TODO -- this should be specifically about applying animation, not paint
mRootLayoutComponent.paint(context.getPaintContext());
+ context.mPaintContext.reset();
// TODO -- should be able to remove this
mRootLayoutComponent.updateVariables(context);
if (DEBUG) {
@@ -843,6 +1011,7 @@
}
}
+ @NonNull
public String[] getStats() {
ArrayList<String> ret = new ArrayList<>();
WireBuffer buffer = new WireBuffer();
@@ -875,7 +1044,7 @@
return ret.toArray(new String[0]);
}
- private int sizeOfComponent(Operation com, WireBuffer tmp) {
+ private int sizeOfComponent(@NonNull Operation com, @NonNull WireBuffer tmp) {
tmp.reset(100);
com.write(tmp);
int size = tmp.getSize();
@@ -883,7 +1052,8 @@
return size;
}
- private int addChildren(Component base, HashMap<String, int[]> map, WireBuffer tmp) {
+ private int addChildren(
+ @NonNull Component base, @NonNull HashMap<String, int[]> map, @NonNull WireBuffer tmp) {
int count = base.mList.size();
for (Operation mOperation : base.mList) {
Class<? extends Operation> c = mOperation.getClass();
@@ -903,6 +1073,7 @@
return count;
}
+ @NonNull
public String toNestedString() {
StringBuilder ret = new StringBuilder();
for (Operation mOperation : mOperations) {
@@ -915,7 +1086,8 @@
return ret.toString();
}
- private void toNestedString(Component base, StringBuilder ret, String indent) {
+ private void toNestedString(
+ @NonNull Component base, @NonNull StringBuilder ret, String indent) {
for (Operation mOperation : base.mList) {
ret.append(mOperation.toString());
ret.append("\n");
diff --git a/core/java/com/android/internal/widget/remotecompose/core/Operation.java b/core/java/com/android/internal/widget/remotecompose/core/Operation.java
index 9f565a2..f1885f9 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/Operation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/Operation.java
@@ -15,6 +15,8 @@
*/
package com.android.internal.widget.remotecompose.core;
+import android.annotation.Nullable;
+
/** Base interface for RemoteCompose operations */
public interface Operation {
@@ -29,5 +31,6 @@
void apply(RemoteContext context);
/** Debug utility to display an operation + indentation */
+ @Nullable
String deepToString(String indent);
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/Operations.java b/core/java/com/android/internal/widget/remotecompose/core/Operations.java
index acebe07..53c45fa 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/Operations.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/Operations.java
@@ -15,6 +15,8 @@
*/
package com.android.internal.widget.remotecompose.core;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.operations.BitmapData;
import com.android.internal.widget.remotecompose.core.operations.ClickArea;
import com.android.internal.widget.remotecompose.core.operations.ClipPath;
@@ -65,15 +67,19 @@
import com.android.internal.widget.remotecompose.core.operations.TextMeasure;
import com.android.internal.widget.remotecompose.core.operations.TextMerge;
import com.android.internal.widget.remotecompose.core.operations.Theme;
+import com.android.internal.widget.remotecompose.core.operations.TouchExpression;
import com.android.internal.widget.remotecompose.core.operations.layout.CanvasContent;
-import com.android.internal.widget.remotecompose.core.operations.layout.ClickModifierEnd;
import com.android.internal.widget.remotecompose.core.operations.layout.ClickModifierOperation;
import com.android.internal.widget.remotecompose.core.operations.layout.ComponentEnd;
import com.android.internal.widget.remotecompose.core.operations.layout.ComponentStart;
import com.android.internal.widget.remotecompose.core.operations.layout.LayoutComponentContent;
import com.android.internal.widget.remotecompose.core.operations.layout.LoopEnd;
import com.android.internal.widget.remotecompose.core.operations.layout.LoopOperation;
+import com.android.internal.widget.remotecompose.core.operations.layout.OperationsListEnd;
import com.android.internal.widget.remotecompose.core.operations.layout.RootLayoutComponent;
+import com.android.internal.widget.remotecompose.core.operations.layout.TouchCancelModifierOperation;
+import com.android.internal.widget.remotecompose.core.operations.layout.TouchDownModifierOperation;
+import com.android.internal.widget.remotecompose.core.operations.layout.TouchUpModifierOperation;
import com.android.internal.widget.remotecompose.core.operations.layout.animation.AnimationSpec;
import com.android.internal.widget.remotecompose.core.operations.layout.managers.BoxLayout;
import com.android.internal.widget.remotecompose.core.operations.layout.managers.CanvasLayout;
@@ -85,15 +91,19 @@
import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.BorderModifierOperation;
import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.ClipRectModifierOperation;
import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.ComponentVisibilityOperation;
+import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.GraphicsLayerModifierOperation;
import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.HeightModifierOperation;
import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.HostActionOperation;
import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.HostNamedActionOperation;
+import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.OffsetModifierOperation;
import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.PaddingModifierOperation;
import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.RoundedClipRectModifierOperation;
+import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.ValueFloatChangeActionOperation;
import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.ValueIntegerChangeActionOperation;
import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.ValueIntegerExpressionChangeActionOperation;
import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.ValueStringChangeActionOperation;
import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.WidthModifierOperation;
+import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.ZIndexModifierOperation;
import com.android.internal.widget.remotecompose.core.operations.utilities.IntMap;
import com.android.internal.widget.remotecompose.core.types.BooleanConstant;
import com.android.internal.widget.remotecompose.core.types.IntegerConstant;
@@ -165,6 +175,7 @@
public static final int DATA_MAP_LOOKUP = 154;
public static final int TEXT_MEASURE = 155;
public static final int TEXT_LENGTH = 156;
+ public static final int TOUCH_EXPRESSION = 157;
///////////////////////////////////////// ======================
@@ -194,8 +205,16 @@
public static final int MODIFIER_ROUNDED_CLIP_RECT = 54;
public static final int MODIFIER_CLICK = 59;
+ public static final int MODIFIER_TOUCH_DOWN = 219;
+ public static final int MODIFIER_TOUCH_UP = 220;
+ public static final int MODIFIER_TOUCH_CANCEL = 225;
- public static final int MODIFIER_CLICK_END = 214;
+ public static final int OPERATIONS_LIST_END = 214;
+
+ public static final int MODIFIER_OFFSET = 221;
+ public static final int MODIFIER_ZINDEX = 223;
+ public static final int MODIFIER_GRAPHICS_LAYER = 224;
+
public static final int LOOP_START = 215;
public static final int LOOP_END = 216;
@@ -206,12 +225,13 @@
public static final int VALUE_INTEGER_CHANGE_ACTION = 212;
public static final int VALUE_STRING_CHANGE_ACTION = 213;
public static final int VALUE_INTEGER_EXPRESSION_CHANGE_ACTION = 218;
+ public static final int VALUE_FLOAT_CHANGE_ACTION = 222;
public static final int ANIMATION_SPEC = 14;
public static final int COMPONENT_VALUE = 150;
- public static UniqueIntMap<CompanionOperation> map = new UniqueIntMap<>();
+ @NonNull public static UniqueIntMap<CompanionOperation> map = new UniqueIntMap<>();
static class UniqueIntMap<T> extends IntMap<T> {
@Override
@@ -289,8 +309,16 @@
map.put(MODIFIER_ROUNDED_CLIP_RECT, RoundedClipRectModifierOperation::read);
map.put(MODIFIER_CLIP_RECT, ClipRectModifierOperation::read);
map.put(MODIFIER_CLICK, ClickModifierOperation::read);
- map.put(MODIFIER_CLICK_END, ClickModifierEnd::read);
+ map.put(MODIFIER_TOUCH_DOWN, TouchDownModifierOperation::read);
+ map.put(MODIFIER_TOUCH_UP, TouchUpModifierOperation::read);
+ map.put(MODIFIER_TOUCH_CANCEL, TouchCancelModifierOperation::read);
map.put(MODIFIER_VISIBILITY, ComponentVisibilityOperation::read);
+ map.put(MODIFIER_OFFSET, OffsetModifierOperation::read);
+ map.put(MODIFIER_ZINDEX, ZIndexModifierOperation::read);
+ map.put(MODIFIER_GRAPHICS_LAYER, GraphicsLayerModifierOperation::read);
+
+ map.put(OPERATIONS_LIST_END, OperationsListEnd::read);
+
map.put(HOST_ACTION, HostActionOperation::read);
map.put(HOST_NAMED_ACTION, HostNamedActionOperation::read);
map.put(VALUE_INTEGER_CHANGE_ACTION, ValueIntegerChangeActionOperation::read);
@@ -298,6 +326,7 @@
VALUE_INTEGER_EXPRESSION_CHANGE_ACTION,
ValueIntegerExpressionChangeActionOperation::read);
map.put(VALUE_STRING_CHANGE_ACTION, ValueStringChangeActionOperation::read);
+ map.put(VALUE_FLOAT_CHANGE_ACTION, ValueFloatChangeActionOperation::read);
map.put(LAYOUT_ROOT, RootLayoutComponent::read);
map.put(LAYOUT_CONTENT, LayoutComponentContent::read);
@@ -315,5 +344,6 @@
map.put(DATA_MAP_LOOKUP, DataMapLookup::read);
map.put(TEXT_MEASURE, TextMeasure::read);
map.put(TEXT_LENGTH, TextLength::read);
+ map.put(TOUCH_EXPRESSION, TouchExpression::read);
}
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/PaintContext.java b/core/java/com/android/internal/widget/remotecompose/core/PaintContext.java
index 13d6f78..1a71afe 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/PaintContext.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/PaintContext.java
@@ -271,4 +271,24 @@
public void needsRepaint() {
mNeedsRepaint = true;
}
+
+ public abstract void startGraphicsLayer(int w, int h);
+
+ public abstract void setGraphicsLayer(
+ float scaleX,
+ float scaleY,
+ float rotationX,
+ float rotationY,
+ float rotationZ,
+ float shadowElevation,
+ float transformOriginX,
+ float transformOriginY,
+ float alpha,
+ int renderEffectId);
+
+ public abstract void endGraphicsLayer();
+
+ public boolean isVisualDebug() {
+ return mContext.isVisualDebug();
+ }
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/PaintOperation.java b/core/java/com/android/internal/widget/remotecompose/core/PaintOperation.java
index 9b7b50f..049e477 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/PaintOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/PaintOperation.java
@@ -15,6 +15,8 @@
*/
package com.android.internal.widget.remotecompose.core;
+import android.annotation.NonNull;
+
/**
* PaintOperation interface, used for operations aimed at painting (while any operation _can_ paint,
* this make it a little more explicit)
@@ -22,7 +24,7 @@
public abstract class PaintOperation implements Operation {
@Override
- public void apply(RemoteContext context) {
+ public void apply(@NonNull RemoteContext context) {
if (context.getMode() == RemoteContext.ContextMode.PAINT) {
PaintContext paintContext = context.getPaintContext();
if (paintContext != null) {
@@ -31,6 +33,7 @@
}
}
+ @NonNull
@Override
public String deepToString(String indent) {
return indent + toString();
diff --git a/core/java/com/android/internal/widget/remotecompose/core/Platform.java b/core/java/com/android/internal/widget/remotecompose/core/Platform.java
index 6725e7e..7fbcfae 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/Platform.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/Platform.java
@@ -15,16 +15,30 @@
*/
package com.android.internal.widget.remotecompose.core;
+import android.annotation.Nullable;
+
/** Services that are needed to be provided by the platform during encoding. */
public interface Platform {
+ @Nullable
byte[] imageToByteArray(Object image);
int getImageWidth(Object image);
int getImageHeight(Object image);
+ @Nullable
float[] pathToFloatArray(Object path);
+ enum LogCategory {
+ DEBUG,
+ INFO,
+ WARN,
+ ERROR,
+ TODO,
+ }
+
+ void log(LogCategory category, String message);
+
Platform None =
new Platform() {
@Override
@@ -46,5 +60,8 @@
public float[] pathToFloatArray(Object path) {
throw new UnsupportedOperationException();
}
+
+ @Override
+ public void log(LogCategory category, String message) {}
};
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeBuffer.java b/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeBuffer.java
index 5b5adc2..7d9439d 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeBuffer.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeBuffer.java
@@ -15,6 +15,9 @@
*/
package com.android.internal.widget.remotecompose.core;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
import com.android.internal.widget.remotecompose.core.operations.BitmapData;
import com.android.internal.widget.remotecompose.core.operations.ClickArea;
import com.android.internal.widget.remotecompose.core.operations.ClipPath;
@@ -64,6 +67,7 @@
import com.android.internal.widget.remotecompose.core.operations.TextMeasure;
import com.android.internal.widget.remotecompose.core.operations.TextMerge;
import com.android.internal.widget.remotecompose.core.operations.Theme;
+import com.android.internal.widget.remotecompose.core.operations.TouchExpression;
import com.android.internal.widget.remotecompose.core.operations.Utils;
import com.android.internal.widget.remotecompose.core.operations.layout.CanvasContent;
import com.android.internal.widget.remotecompose.core.operations.layout.ComponentEnd;
@@ -81,8 +85,11 @@
import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.BackgroundModifierOperation;
import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.BorderModifierOperation;
import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.ClipRectModifierOperation;
+import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.GraphicsLayerModifierOperation;
+import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.OffsetModifierOperation;
import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.PaddingModifierOperation;
import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.RoundedClipRectModifierOperation;
+import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.ZIndexModifierOperation;
import com.android.internal.widget.remotecompose.core.operations.paint.PaintBundle;
import com.android.internal.widget.remotecompose.core.operations.utilities.NanMap;
import com.android.internal.widget.remotecompose.core.operations.utilities.easing.FloatAnimation;
@@ -111,7 +118,7 @@
public static final int EASING_EASE_OUT_BOUNCE = FloatAnimation.EASE_OUT_BOUNCE;
public static final int EASING_EASE_OUT_ELASTIC = FloatAnimation.EASE_OUT_ELASTIC;
WireBuffer mBuffer = new WireBuffer();
- Platform mPlatform = null;
+ @Nullable Platform mPlatform = null;
RemoteComposeState mRemoteComposeState;
private static final boolean DEBUG = false;
@@ -143,6 +150,7 @@
return mLastComponentId;
}
+ @Nullable
public Platform getPlatform() {
return mPlatform;
}
@@ -172,7 +180,11 @@
* @param capabilities bitmask indicating needed capabilities (unused for now)
*/
public void header(
- int width, int height, String contentDescription, float density, long capabilities) {
+ int width,
+ int height,
+ @Nullable String contentDescription,
+ float density,
+ long capabilities) {
Header.apply(mBuffer, width, height, density, capabilities);
int contentDescriptionId = 0;
if (contentDescription != null) {
@@ -219,7 +231,7 @@
int dstTop,
int dstRight,
int dstBottom,
- String contentDescription) {
+ @Nullable String contentDescription) {
int imageId = mRemoteComposeState.dataGetId(image);
if (imageId == -1) {
imageId = mRemoteComposeState.cacheData(image);
@@ -267,7 +279,7 @@
*
* @param text the string to inject in the buffer
*/
- public int addText(String text) {
+ public int addText(@NonNull String text) {
int id = mRemoteComposeState.dataGetId(text);
if (id == -1) {
id = mRemoteComposeState.cacheData(text);
@@ -289,12 +301,12 @@
*/
public void addClickArea(
int id,
- String contentDescription,
+ @Nullable String contentDescription,
float left,
float top,
float right,
float bottom,
- String metadata) {
+ @Nullable String metadata) {
int contentDescriptionId = 0;
if (contentDescription != null) {
contentDescriptionId = addText(contentDescription);
@@ -380,7 +392,7 @@
float top,
float right,
float bottom,
- String contentDescription) {
+ @Nullable String contentDescription) {
int imageId = mRemoteComposeState.dataGetId(image);
if (imageId == -1) {
imageId = mRemoteComposeState.cacheData(image);
@@ -411,7 +423,7 @@
float top,
float right,
float bottom,
- String contentDescription) {
+ @Nullable String contentDescription) {
int contentDescriptionId = 0;
if (contentDescription != null) {
contentDescriptionId = addText(contentDescription);
@@ -445,7 +457,7 @@
float dstBottom,
int scaleType,
float scaleFactor,
- String contentDescription) {
+ @Nullable String contentDescription) {
int imageId = mRemoteComposeState.dataGetId(image);
if (imageId == -1) {
imageId = mRemoteComposeState.cacheData(image);
@@ -500,7 +512,7 @@
* @param image drawScaledBitmap
* @return id of the image useful with
*/
- public int addBitmap(Object image, String name) {
+ public int addBitmap(Object image, @NonNull String name) {
int imageId = mRemoteComposeState.dataGetId(image);
if (imageId == -1) {
imageId = mRemoteComposeState.cacheData(image);
@@ -521,7 +533,7 @@
* @param id of the Bitmap
* @param name Name of the color
*/
- public void setBitmapName(int id, String name) {
+ public void setBitmapName(int id, @NonNull String name) {
NamedVariable.apply(mBuffer, id, NamedVariable.IMAGE_TYPE, name);
}
@@ -551,7 +563,7 @@
float dstBottom,
int scaleType,
float scaleFactor,
- String contentDescription) {
+ @Nullable String contentDescription) {
int contentDescriptionId = 0;
if (contentDescription != null) {
contentDescriptionId = addText(contentDescription);
@@ -669,7 +681,7 @@
* @param hOffset The distance along the path to add to the text's starting position
* @param vOffset The distance above(-) or below(+) the path to position the text
*/
- public void addDrawTextOnPath(String text, Object path, float hOffset, float vOffset) {
+ public void addDrawTextOnPath(@NonNull String text, Object path, float hOffset, float vOffset) {
int pathId = mRemoteComposeState.dataGetId(path);
if (pathId == -1) { // never been seen before
pathId = addPathData(path);
@@ -692,7 +704,7 @@
* @param rtl Draw RTTL
*/
public void addDrawTextRun(
- String text,
+ @NonNull String text,
int start,
int end,
int contextStart,
@@ -749,7 +761,8 @@
* @param panY position text -1.0=above, 0.0=center, 1.0=below, Nan=baseline
* @param flags 1 = RTL
*/
- public void drawTextAnchored(String text, float x, float y, float panX, float panY, int flags) {
+ public void drawTextAnchored(
+ @NonNull String text, float x, float y, float panX, float panY, int flags) {
int textId = addText(text);
DrawTextAnchored.apply(mBuffer, textId, x, y, panX, panY, flags);
}
@@ -760,7 +773,7 @@
* @param text
* @return
*/
- public int createTextId(String text) {
+ public int createTextId(@NonNull String text) {
return addText(text);
}
@@ -891,7 +904,7 @@
*
* @param paint
*/
- public void addPaint(PaintBundle paint) {
+ public void addPaint(@NonNull PaintBundle paint) {
PaintData.apply(mBuffer, paint);
}
@@ -912,7 +925,8 @@
}
}
- public static void readNextOperation(WireBuffer buffer, ArrayList<Operation> operations) {
+ public static void readNextOperation(
+ @NonNull WireBuffer buffer, ArrayList<Operation> operations) {
int opId = buffer.readByte();
if (DEBUG) {
Utils.log(">> " + opId);
@@ -924,6 +938,7 @@
operation.read(buffer, operations);
}
+ @NonNull
RemoteComposeBuffer copy() {
ArrayList<Operation> operations = new ArrayList<>();
inflateFromBuffer(operations);
@@ -935,33 +950,38 @@
Theme.apply(mBuffer, theme);
}
+ @NonNull
static String version() {
return "v1.0";
}
- public static RemoteComposeBuffer fromFile(String path, RemoteComposeState remoteComposeState)
- throws IOException {
+ @NonNull
+ public static RemoteComposeBuffer fromFile(
+ @NonNull String path, RemoteComposeState remoteComposeState) throws IOException {
RemoteComposeBuffer buffer = new RemoteComposeBuffer(remoteComposeState);
read(new File(path), buffer);
return buffer;
}
- public RemoteComposeBuffer fromFile(File file, RemoteComposeState remoteComposeState)
+ @NonNull
+ public RemoteComposeBuffer fromFile(@NonNull File file, RemoteComposeState remoteComposeState)
throws IOException {
RemoteComposeBuffer buffer = new RemoteComposeBuffer(remoteComposeState);
read(file, buffer);
return buffer;
}
+ @NonNull
public static RemoteComposeBuffer fromInputStream(
- InputStream inputStream, RemoteComposeState remoteComposeState) {
+ @NonNull InputStream inputStream, RemoteComposeState remoteComposeState) {
RemoteComposeBuffer buffer = new RemoteComposeBuffer(remoteComposeState);
read(inputStream, buffer);
return buffer;
}
+ @NonNull
RemoteComposeBuffer copyFromOperations(
- ArrayList<Operation> operations, RemoteComposeBuffer buffer) {
+ @NonNull ArrayList<Operation> operations, @NonNull RemoteComposeBuffer buffer) {
for (Operation operation : operations) {
operation.write(buffer.mBuffer);
@@ -975,7 +995,7 @@
* @param buffer a RemoteComposeBuffer
* @param file a target file
*/
- public void write(RemoteComposeBuffer buffer, File file) {
+ public void write(@NonNull RemoteComposeBuffer buffer, @NonNull File file) {
try {
FileOutputStream fd = new FileOutputStream(file);
fd.write(buffer.mBuffer.getBuffer(), 0, buffer.mBuffer.getSize());
@@ -986,12 +1006,12 @@
}
}
- static void read(File file, RemoteComposeBuffer buffer) throws IOException {
+ static void read(@NonNull File file, @NonNull RemoteComposeBuffer buffer) throws IOException {
FileInputStream fd = new FileInputStream(file);
read(fd, buffer);
}
- public static void read(InputStream fd, RemoteComposeBuffer buffer) {
+ public static void read(@NonNull InputStream fd, @NonNull RemoteComposeBuffer buffer) {
try {
byte[] bytes = readAllBytes(fd);
buffer.reset(bytes.length);
@@ -1002,7 +1022,7 @@
}
}
- private static byte[] readAllBytes(InputStream is) throws IOException {
+ private static byte[] readAllBytes(@NonNull InputStream is) throws IOException {
byte[] buff = new byte[32 * 1024]; // moderate size buff to start
int red = 0;
while (true) {
@@ -1176,20 +1196,59 @@
* @param value A RPN style float operation i.e. "4, 3, ADD" outputs 7
* @return NaN id of the result of the calculation
*/
- public float addAnimatedFloat(float... value) {
+ public float addAnimatedFloat(@NonNull float... value) {
int id = mRemoteComposeState.cacheData(value);
FloatExpression.apply(mBuffer, id, value, null);
return Utils.asNan(id);
}
/**
+ * Add a touch handle system
+ *
+ * @param value the default value
+ * @param min the minimum value
+ * @param max the maximum value
+ * @param velocityId the id for the velocity TODO support in v2
+ * @param exp The Float Expression
+ * @param touchMode the touch up handling behaviour
+ * @param touchSpec the touch up handling parameters
+ * @param easingSpec the easing parameter TODO support in v2
+ * @return id of the variable to be used controlled by touch handling
+ */
+ public float addTouchExpression(
+ float value,
+ float min,
+ float max,
+ float velocityId,
+ int touchEffects,
+ float[] exp,
+ int touchMode,
+ float[] touchSpec,
+ float[] easingSpec) {
+ int id = mRemoteComposeState.nextId();
+ TouchExpression.apply(
+ mBuffer,
+ id,
+ value,
+ min,
+ max,
+ velocityId,
+ touchEffects,
+ exp,
+ touchMode,
+ touchSpec,
+ easingSpec);
+ return Utils.asNan(id);
+ }
+
+ /**
* Add a float that is a computation based on variables. see packAnimation
*
* @param value A RPN style float operation i.e. "4, 3, ADD" outputs 7
* @param animation Array of floats that represents animation
* @return NaN id of the result of the calculation
*/
- public float addAnimatedFloat(float[] value, float[] animation) {
+ public float addAnimatedFloat(@NonNull float[] value, float[] animation) {
int id = mRemoteComposeState.cacheData(value);
FloatExpression.apply(mBuffer, id, value, animation);
return Utils.asNan(id);
@@ -1228,7 +1287,7 @@
* @param values
* @return the id of the array, encoded as a float NaN
*/
- public float addFloatArray(float[] values) {
+ public float addFloatArray(@NonNull float[] values) {
int id = mRemoteComposeState.cacheData(values, NanMap.TYPE_ARRAY);
DataListFloat.apply(mBuffer, id, values);
return Utils.asNan(id);
@@ -1240,7 +1299,7 @@
* @param values array of floats to be individually stored
* @return id of the list
*/
- public float addFloatList(float[] values) {
+ public float addFloatList(@NonNull float[] values) {
int[] listId = new int[values.length];
for (int i = 0; i < listId.length; i++) {
listId[i] = mRemoteComposeState.cacheFloat(values[i]);
@@ -1255,7 +1314,7 @@
* @param listId array id to be stored
* @return id of the list
*/
- public float addList(int[] listId) {
+ public float addList(@NonNull int[] listId) {
int id = mRemoteComposeState.cacheData(listId, NanMap.TYPE_ARRAY);
DataListIds.apply(mBuffer, id, listId);
return Utils.asNan(id);
@@ -1268,7 +1327,7 @@
* @param values
* @return the id of the map, encoded as a float NaN
*/
- public float addFloatMap(String[] keys, float[] values) {
+ public float addFloatMap(@NonNull String[] keys, @NonNull float[] values) {
int[] listId = new int[values.length];
byte[] type = new byte[values.length];
for (int i = 0; i < listId.length; i++) {
@@ -1286,7 +1345,7 @@
* @param listId
* @return the id of the map, encoded as a float NaN
*/
- public int addMap(String[] keys, byte[] types, int[] listId) {
+ public int addMap(@NonNull String[] keys, byte[] types, int[] listId) {
int id = mRemoteComposeState.cacheData(listId, NanMap.TYPE_ARRAY);
DataMapIds.apply(mBuffer, id, keys, types, listId);
return id;
@@ -1331,7 +1390,7 @@
* @param value array of values to calculate maximum 32
* @return the id as an integer
*/
- public int addIntegerExpression(int mask, int[] value) {
+ public int addIntegerExpression(int mask, @NonNull int[] value) {
int id = mRemoteComposeState.cacheData(value);
IntegerExpression.apply(mBuffer, id, mask, value);
return id;
@@ -1474,7 +1533,7 @@
* @param id of the color
* @param name Name of the color
*/
- public void setColorName(int id, String name) {
+ public void setColorName(int id, @NonNull String name) {
NamedVariable.apply(mBuffer, id, NamedVariable.COLOR_TYPE, name);
}
@@ -1484,7 +1543,7 @@
* @param id of the string
* @param name name of the string
*/
- public void setStringName(int id, String name) {
+ public void setStringName(int id, @NonNull String name) {
NamedVariable.apply(mBuffer, id, NamedVariable.STRING_TYPE, name);
}
@@ -1576,6 +1635,72 @@
}
/**
+ * Add an offset modifier
+ *
+ * @param x x offset
+ * @param y y offset
+ */
+ public void addModifierOffset(float x, float y) {
+ OffsetModifierOperation.apply(mBuffer, x, y);
+ }
+
+ /**
+ * Add a zIndex modifier
+ *
+ * @param value z-Index value
+ */
+ public void addModifierZIndex(float value) {
+ ZIndexModifierOperation.apply(mBuffer, value);
+ }
+
+ /**
+ * Add a graphics layer
+ *
+ * @param scaleX
+ * @param scaleY
+ * @param rotationX
+ * @param rotationY
+ * @param rotationZ
+ * @param shadowElevation
+ * @param transformOriginX
+ * @param transformOriginY
+ */
+ public void addModifierGraphicsLayer(
+ float scaleX,
+ float scaleY,
+ float rotationX,
+ float rotationY,
+ float rotationZ,
+ float shadowElevation,
+ float transformOriginX,
+ float transformOriginY,
+ float alpha,
+ float cameraDistance,
+ int blendMode,
+ int spotShadowColorId,
+ int ambientShadowColorId,
+ int colorFilterId,
+ int renderEffectId) {
+ GraphicsLayerModifierOperation.apply(
+ mBuffer,
+ scaleX,
+ scaleY,
+ rotationX,
+ rotationY,
+ rotationZ,
+ shadowElevation,
+ transformOriginX,
+ transformOriginY,
+ alpha,
+ cameraDistance,
+ blendMode,
+ spotShadowColorId,
+ ambientShadowColorId,
+ colorFilterId,
+ renderEffectId);
+ }
+
+ /**
* Sets the clip based on rounded clip rect
*
* @param topStart
@@ -1721,7 +1846,8 @@
float fontSize,
int fontStyle,
float fontWeight,
- String fontFamily) {
+ @Nullable String fontFamily,
+ int textAlign) {
mLastComponentId = getComponentId(componentId);
int fontFamilyId = -1;
if (fontFamily != null) {
@@ -1736,6 +1862,11 @@
fontSize,
fontStyle,
fontWeight,
- fontFamilyId);
+ fontFamilyId,
+ textAlign);
+ }
+
+ public int createID(int type) {
+ return mRemoteComposeState.nextId(type);
}
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeState.java b/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeState.java
index 51445f2..3039328 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeState.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeState.java
@@ -15,6 +15,9 @@
*/
package com.android.internal.widget.remotecompose.core;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
import com.android.internal.widget.remotecompose.core.operations.utilities.ArrayAccess;
import com.android.internal.widget.remotecompose.core.operations.utilities.CollectionsAccess;
import com.android.internal.widget.remotecompose.core.operations.utilities.DataMap;
@@ -50,10 +53,11 @@
private final boolean[] mDataOverride = new boolean[MAX_DATA];
private final boolean[] mIntegerOverride = new boolean[MAX_DATA];
+ private final boolean[] mFloatOverride = new boolean[MAX_DATA];
private int mNextId = START_ID;
- private int[] mIdMaps = new int[] {START_ID, NanMap.START_VAR, NanMap.START_ARRAY};
- private RemoteContext mRemoteContext = null;
+ @NonNull private int[] mIdMaps = new int[] {START_ID, NanMap.START_VAR, NanMap.START_ARRAY};
+ @Nullable private RemoteContext mRemoteContext = null;
/**
* Get Object based on id. The system will cache things like bitmaps Paths etc. They can be
@@ -62,6 +66,7 @@
* @param id
* @return
*/
+ @Nullable
public Object getFromId(int id) {
return mIntDataMap.get(id);
}
@@ -158,10 +163,28 @@
/** Insert an float item in the cache */
public void updateFloat(int id, float value) {
+ if (!mFloatOverride[id]) {
+ float previous = mFloatMap.get(id);
+ if (previous != value) {
+ mFloatMap.put(id, value);
+ mIntegerMap.put(id, (int) value);
+ updateListeners(id);
+ }
+ }
+ }
+
+ /**
+ * Adds a float Override.
+ *
+ * @param id
+ * @param value the new value
+ */
+ public void overrideFloat(int id, float value) {
float previous = mFloatMap.get(id);
if (previous != value) {
mFloatMap.put(id, value);
mIntegerMap.put(id, (int) value);
+ mFloatOverride[id] = true;
updateListeners(id);
}
}
@@ -294,6 +317,16 @@
}
/**
+ * Clear the float override
+ *
+ * @param id the float id to clear
+ */
+ public void clearFloatOverride(int id) {
+ mFloatOverride[id] = false;
+ updateListeners(id);
+ }
+
+ /**
* Method to determine if a cached value has been written to the documents WireBuffer based on
* its id.
*/
@@ -322,7 +355,8 @@
}
/**
- * Get the next available id
+ * Get the next available id 0 is normal (float,int,String,color) 1 is VARIABLES 2 is
+ * collections
*
* @return
*/
@@ -342,8 +376,8 @@
mNextId = id;
}
- IntMap<ArrayList<VariableSupport>> mVarListeners = new IntMap<>();
- ArrayList<VariableSupport> mAllVarListeners = new ArrayList<>();
+ @NonNull IntMap<ArrayList<VariableSupport>> mVarListeners = new IntMap<>();
+ @NonNull ArrayList<VariableSupport> mAllVarListeners = new ArrayList<>();
private void add(int id, VariableSupport variableSupport) {
ArrayList<VariableSupport> v = mVarListeners.get(id);
diff --git a/core/java/com/android/internal/widget/remotecompose/core/RemoteContext.java b/core/java/com/android/internal/widget/remotecompose/core/RemoteContext.java
index 1066e7d..23cc5b8 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/RemoteContext.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/RemoteContext.java
@@ -15,6 +15,8 @@
*/
package com.android.internal.widget.remotecompose.core;
+import android.annotation.Nullable;
+
import com.android.internal.widget.remotecompose.core.operations.FloatExpression;
import com.android.internal.widget.remotecompose.core.operations.ShaderData;
import com.android.internal.widget.remotecompose.core.operations.Theme;
@@ -40,10 +42,12 @@
protected CoreDocument mDocument;
public RemoteComposeState mRemoteComposeState;
long mStart = System.nanoTime(); // todo This should be set at a hi level
- protected PaintContext mPaintContext = null;
+ @Nullable protected PaintContext mPaintContext = null;
+ protected float mDensity = 2.75f;
+
ContextMode mMode = ContextMode.UNSET;
- boolean mDebug = false;
+ int mDebug = 0;
private int mTheme = Theme.UNSPECIFIED;
@@ -56,6 +60,14 @@
public Component lastComponent;
public long currentTime = 0L;
+ public float getDensity() {
+ return mDensity;
+ }
+
+ public void setDensity(float density) {
+ mDensity = density;
+ }
+
public boolean isAnimationEnabled() {
return mAnimate;
}
@@ -173,12 +185,22 @@
public abstract void runAction(int id, String metadata);
- public abstract void runNamedAction(int textId);
+ // TODO: we might add an interface to group all valid parameter types
+ public abstract void runNamedAction(int textId, Object value);
public abstract void putObject(int mId, Object command);
public abstract Object getObject(int mId);
+ public void addTouchListener(TouchListener touchExpression) {}
+
+ /**
+ * Vibrate the device
+ *
+ * @param type 0 = none, 1-21 ,see HapticFeedbackConstants
+ */
+ public abstract void hapticEffect(int type);
+
/**
* The context can be used in a few different mode, allowing operations to skip being executed:
* - UNSET : all operations will get executed - DATA : only operations dealing with DATA (eg
@@ -206,6 +228,7 @@
this.mMode = mode;
}
+ @Nullable
public PaintContext getPaintContext() {
return mPaintContext;
}
@@ -219,10 +242,14 @@
}
public boolean isDebug() {
- return mDebug;
+ return mDebug == 1;
}
- public void setDebug(boolean debug) {
+ public boolean isVisualDebug() {
+ return mDebug == 2;
+ }
+
+ public void setDebug(int debug) {
this.mDebug = debug;
}
@@ -314,6 +341,14 @@
public abstract void loadFloat(int id, float value);
/**
+ * Override an existing float value
+ *
+ * @param id
+ * @param value
+ */
+ public abstract void overrideFloat(int id, float value);
+
+ /**
* Load a integer
*
* @param id id of the integer
@@ -321,8 +356,20 @@
*/
public abstract void loadInteger(int id, int value);
+ /**
+ * Override an existing int value
+ *
+ * @param id
+ * @param value
+ */
public abstract void overrideInteger(int id, int value);
+ /**
+ * Override an existing text value
+ *
+ * @param id
+ * @param valueId
+ */
public abstract void overrideText(int id, int valueId);
/**
@@ -400,6 +447,25 @@
public static final int ID_OFFSET_TO_UTC = 10;
public static final int ID_WEEK_DAY = 11;
public static final int ID_DAY_OF_MONTH = 12;
+ public static final int ID_TOUCH_POS_X = 13;
+ public static final int ID_TOUCH_POS_Y = 14;
+
+ public static final int ID_TOUCH_VEL_X = 15;
+ public static final int ID_TOUCH_VEL_Y = 16;
+
+ public static final int ID_ACCELERATION_X = 17;
+ public static final int ID_ACCELERATION_Y = 18;
+ public static final int ID_ACCELERATION_Z = 19;
+
+ public static final int ID_GYRO_ROT_X = 20;
+ public static final int ID_GYRO_ROT_Y = 21;
+ public static final int ID_GYRO_ROT_Z = 22;
+
+ public static final int ID_MAGNETIC_X = 23;
+ public static final int ID_MAGNETIC_Y = 24;
+ public static final int ID_MAGNETIC_Z = 25;
+
+ public static final int ID_LIGHT = 26;
/** CONTINUOUS_SEC is seconds from midnight looping every hour 0-3600 */
public static final float FLOAT_CONTINUOUS_SEC = Utils.asNan(ID_CONTINUOUS_SEC);
@@ -426,9 +492,52 @@
public static final float FLOAT_WINDOW_HEIGHT = Utils.asNan(ID_WINDOW_HEIGHT);
public static final float FLOAT_COMPONENT_WIDTH = Utils.asNan(ID_COMPONENT_WIDTH);
public static final float FLOAT_COMPONENT_HEIGHT = Utils.asNan(ID_COMPONENT_HEIGHT);
- // ID_OFFSET_TO_UTC is the offset from UTC in sec (typically / 3600f)
+
+ /** ID_OFFSET_TO_UTC is the offset from UTC in sec (typically / 3600f) */
public static final float FLOAT_OFFSET_TO_UTC = Utils.asNan(ID_OFFSET_TO_UTC);
+ /** TOUCH_POS_X is the x position of the touch */
+ public static final float FLOAT_TOUCH_POS_X = Utils.asNan(ID_TOUCH_POS_X);
+
+ /** TOUCH_POS_Y is the y position of the touch */
+ public static final float FLOAT_TOUCH_POS_Y = Utils.asNan(ID_TOUCH_POS_Y);
+
+ /** TOUCH_VEL_X is the x velocity of the touch */
+ public static final float FLOAT_TOUCH_VEL_X = Utils.asNan(ID_TOUCH_VEL_X);
+
+ /** TOUCH_VEL_Y is the x velocity of the touch */
+ public static final float FLOAT_TOUCH_VEL_Y = Utils.asNan(ID_TOUCH_VEL_Y);
+
+ /** X acceleration sensor value in M/s^2 */
+ public static final float FLOAT_ACCELERATION_X = Utils.asNan(ID_ACCELERATION_X);
+
+ /** Y acceleration sensor value in M/s^2 */
+ public static final float FLOAT_ACCELERATION_Y = Utils.asNan(ID_ACCELERATION_Y);
+
+ /** Z acceleration sensor value in M/s^2 */
+ public static final float FLOAT_ACCELERATION_Z = Utils.asNan(ID_ACCELERATION_Z);
+
+ /** X Gyroscope rotation rate sensor value in radians/second */
+ public static final float FLOAT_GYRO_ROT_X = Utils.asNan(ID_GYRO_ROT_X);
+
+ /** Y Gyroscope rotation rate sensor value in radians/second */
+ public static final float FLOAT_GYRO_ROT_Y = Utils.asNan(ID_GYRO_ROT_Y);
+
+ /** Z Gyroscope rotation rate sensor value in radians/second */
+ public static final float FLOAT_GYRO_ROT_Z = Utils.asNan(ID_GYRO_ROT_Z);
+
+ /** Ambient magnetic field in X. sensor value in micro-Tesla (uT) */
+ public static final float FLOAT_MAGNETIC_X = Utils.asNan(ID_MAGNETIC_X);
+
+ /** Ambient magnetic field in Y. sensor value in micro-Tesla (uT) */
+ public static final float FLOAT_MAGNETIC_Y = Utils.asNan(ID_MAGNETIC_Y);
+
+ /** Ambient magnetic field in Z. sensor value in micro-Tesla (uT) */
+ public static final float FLOAT_MAGNETIC_Z = Utils.asNan(ID_MAGNETIC_Z);
+
+ /** Ambient light level in SI lux */
+ public static final float FLOAT_LIGHT = Utils.asNan(ID_LIGHT);
+
///////////////////////////////////////////////////////////////////////////////////////////////
// Click handling
///////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/core/java/com/android/internal/widget/remotecompose/core/TimeVariables.java b/core/java/com/android/internal/widget/remotecompose/core/TimeVariables.java
index fa0cf3f..14aed2f 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/TimeVariables.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/TimeVariables.java
@@ -15,6 +15,8 @@
*/
package com.android.internal.widget.remotecompose.core;
+import android.annotation.NonNull;
+
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneId;
@@ -27,7 +29,7 @@
*
* @param context
*/
- public void updateTime(RemoteContext context) {
+ public void updateTime(@NonNull RemoteContext context) {
LocalDateTime dateTime =
LocalDateTime.now(ZoneId.systemDefault()); // TODO, pass in a timezone explicitly?
// This define the time in the format
diff --git a/core/java/com/android/internal/widget/remotecompose/core/TouchListener.java b/core/java/com/android/internal/widget/remotecompose/core/TouchListener.java
new file mode 100644
index 0000000..3dda678
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/TouchListener.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2024 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.internal.widget.remotecompose.core;
+
+public interface TouchListener {
+ void touchDown(RemoteContext context, float x, float y);
+
+ void touchUp(RemoteContext context, float x, float y, float dx, float dy);
+
+ void touchDrag(RemoteContext context, float x, float y);
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/WireBuffer.java b/core/java/com/android/internal/widget/remotecompose/core/WireBuffer.java
index c71b490..738e42b 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/WireBuffer.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/WireBuffer.java
@@ -15,6 +15,8 @@
*/
package com.android.internal.widget.remotecompose.core;
+import android.annotation.NonNull;
+
import java.util.Arrays;
/** The base communication buffer capable of encoding and decoding various types */
@@ -184,11 +186,13 @@
return b;
}
+ @NonNull
public String readUTF8() {
byte[] stringBuffer = readBuffer();
return new String(stringBuffer);
}
+ @NonNull
public String readUTF8(int maxSize) {
byte[] stringBuffer = readBuffer(maxSize);
return new String(stringBuffer);
@@ -250,7 +254,7 @@
writeLong(Double.doubleToRawLongBits(value));
}
- public void writeBuffer(byte[] b) {
+ public void writeBuffer(@NonNull byte[] b) {
resize(b.length + 4);
writeInt(b.length);
for (int i = 0; i < b.length; i++) {
@@ -259,7 +263,7 @@
mSize += b.length;
}
- public void writeUTF8(String content) {
+ public void writeUTF8(@NonNull String content) {
byte[] buffer = content.getBytes();
writeBuffer(buffer);
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/documentation/DocumentedOperation.java b/core/java/com/android/internal/widget/remotecompose/core/documentation/DocumentedOperation.java
index c33ae24..5edecaa 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/documentation/DocumentedOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/documentation/DocumentedOperation.java
@@ -15,6 +15,8 @@
*/
package com.android.internal.widget.remotecompose.core.documentation;
+import android.annotation.NonNull;
+
import java.util.ArrayList;
public class DocumentedOperation {
@@ -40,12 +42,13 @@
boolean mWIP;
String mTextExamples;
- ArrayList<StringPair> mExamples = new ArrayList<>();
- ArrayList<OperationField> mFields = new ArrayList<>();
- String mVarSize = "";
+ @NonNull ArrayList<StringPair> mExamples = new ArrayList<>();
+ @NonNull ArrayList<OperationField> mFields = new ArrayList<>();
+ @NonNull String mVarSize = "";
int mExamplesWidth = 100;
int mExamplesHeight = 100;
+ @NonNull
public static String getType(int type) {
switch (type) {
case INT:
@@ -85,6 +88,7 @@
this(category, id, name, false);
}
+ @NonNull
public ArrayList<OperationField> getFields() {
return mFields;
}
@@ -105,6 +109,7 @@
return mWIP;
}
+ @NonNull
public String getVarSize() {
return mVarSize;
}
@@ -129,6 +134,7 @@
return mTextExamples;
}
+ @NonNull
public ArrayList<StringPair> getExamples() {
return mExamples;
}
@@ -141,16 +147,19 @@
return mExamplesHeight;
}
+ @NonNull
public DocumentedOperation field(int type, String name, String description) {
mFields.add(new OperationField(type, name, description));
return this;
}
+ @NonNull
public DocumentedOperation field(int type, String name, String varSize, String description) {
mFields.add(new OperationField(type, name, varSize, description));
return this;
}
+ @NonNull
public DocumentedOperation possibleValues(String name, int value) {
if (!mFields.isEmpty()) {
mFields.get(mFields.size() - 1).possibleValue(name, "" + value);
@@ -158,21 +167,25 @@
return this;
}
+ @NonNull
public DocumentedOperation description(String description) {
mDescription = description;
return this;
}
+ @NonNull
public DocumentedOperation examples(String examples) {
mTextExamples = examples;
return this;
}
+ @NonNull
public DocumentedOperation exampleImage(String name, String imagePath) {
mExamples.add(new StringPair(name, imagePath));
return this;
}
+ @NonNull
public DocumentedOperation examplesDimension(int width, int height) {
mExamplesWidth = width;
mExamplesHeight = height;
diff --git a/core/java/com/android/internal/widget/remotecompose/core/documentation/OperationField.java b/core/java/com/android/internal/widget/remotecompose/core/documentation/OperationField.java
index c770483..cbb5ca9 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/documentation/OperationField.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/documentation/OperationField.java
@@ -15,15 +15,18 @@
*/
package com.android.internal.widget.remotecompose.core.documentation;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
import java.util.ArrayList;
public class OperationField {
int mType;
String mName;
String mDescription;
- String mVarSize = null;
+ @Nullable String mVarSize = null;
- ArrayList<StringPair> mPossibleValues = new ArrayList<>();
+ @NonNull ArrayList<StringPair> mPossibleValues = new ArrayList<>();
public OperationField(int type, String name, String description) {
mType = type;
@@ -50,6 +53,7 @@
return mDescription;
}
+ @NonNull
public ArrayList<StringPair> getPossibleValues() {
return mPossibleValues;
}
@@ -62,6 +66,7 @@
return !mPossibleValues.isEmpty();
}
+ @Nullable
public String getVarSize() {
return mVarSize;
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/BitmapData.java b/core/java/com/android/internal/widget/remotecompose/core/operations/BitmapData.java
index 20ba8c31..8da0e18 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/BitmapData.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/BitmapData.java
@@ -18,6 +18,8 @@
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT;
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT_ARRAY;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.RemoteContext;
@@ -58,15 +60,17 @@
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(buffer, mImageId, mImageWidth, mImageHeight, mBitmap);
}
+ @NonNull
@Override
public String toString() {
return "BITMAP DATA " + mImageId;
}
+ @NonNull
public static String name() {
return CLASS_NAME;
}
@@ -75,7 +79,12 @@
return OP_CODE;
}
- public static void apply(WireBuffer buffer, int imageId, int width, int height, byte[] bitmap) {
+ public static void apply(
+ @NonNull WireBuffer buffer,
+ int imageId,
+ int width,
+ int height,
+ @NonNull byte[] bitmap) {
buffer.start(OP_CODE);
buffer.writeInt(imageId);
buffer.writeInt(width);
@@ -83,7 +92,7 @@
buffer.writeBuffer(bitmap);
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int imageId = buffer.readInt();
int width = buffer.readInt();
int height = buffer.readInt();
@@ -97,7 +106,7 @@
operations.add(new BitmapData(imageId, width, height, bitmap));
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Data Operations", OP_CODE, CLASS_NAME)
.description("Bitmap data")
.field(DocumentedOperation.INT, "id", "id of bitmap data")
@@ -107,17 +116,18 @@
}
@Override
- public void apply(RemoteContext context) {
+ public void apply(@NonNull RemoteContext context) {
context.loadBitmap(mImageId, mImageWidth, mImageHeight, mBitmap);
}
+ @NonNull
@Override
public String deepToString(String indent) {
return indent + toString();
}
@Override
- public void serializeToString(int indent, StringSerializer serializer) {
+ public void serializeToString(int indent, @NonNull StringSerializer serializer) {
serializer.append(
indent,
CLASS_NAME + " id " + mImageId + " (" + mImageWidth + "x" + mImageHeight + ")");
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/ClickArea.java b/core/java/com/android/internal/widget/remotecompose/core/operations/ClickArea.java
index 8b9e5a8..83d0ac7 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/ClickArea.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/ClickArea.java
@@ -15,6 +15,8 @@
*/
package com.android.internal.widget.remotecompose.core.operations;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.RemoteComposeOperation;
@@ -67,10 +69,11 @@
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(buffer, mId, mContentDescription, mLeft, mTop, mRight, mBottom, mMetadata);
}
+ @NonNull
@Override
public String toString() {
return "CLICK_AREA <"
@@ -97,18 +100,20 @@
}
@Override
- public void apply(RemoteContext context) {
+ public void apply(@NonNull RemoteContext context) {
if (context.getMode() != RemoteContext.ContextMode.DATA) {
return;
}
context.addClickArea(mId, mContentDescription, mLeft, mTop, mRight, mBottom, mMetadata);
}
+ @NonNull
@Override
public String deepToString(String indent) {
return indent + toString();
}
+ @NonNull
public static String name() {
return CLASS_NAME;
}
@@ -118,7 +123,7 @@
}
public static void apply(
- WireBuffer buffer,
+ @NonNull WireBuffer buffer,
int id,
int contentDescription,
float left,
@@ -136,7 +141,7 @@
buffer.writeInt(metadata);
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int id = buffer.readInt();
int contentDescription = buffer.readInt();
float left = buffer.readFloat();
@@ -149,7 +154,7 @@
operations.add(clickArea);
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Canvas Operations", OP_CODE, CLASS_NAME)
.description("Define a region you can click on")
.field(DocumentedOperation.FLOAT, "left", "The left side of the region")
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/ClipPath.java b/core/java/com/android/internal/widget/remotecompose/core/operations/ClipPath.java
index 96b600a..db93829 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/ClipPath.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/ClipPath.java
@@ -15,6 +15,8 @@
*/
package com.android.internal.widget.remotecompose.core.operations;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.PaintContext;
@@ -57,16 +59,17 @@
public static final int UNDEFINED = PATH_CLIP_UNDEFINED;
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(buffer, mId);
}
+ @NonNull
@Override
public String toString() {
return "ClipPath " + mId + ";";
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int pack = buffer.readInt();
int id = pack & 0xFFFFF;
int regionOp = pack >> 24;
@@ -74,6 +77,7 @@
operations.add(op);
}
+ @NonNull
public static String name() {
return CLASS_NAME;
}
@@ -82,19 +86,19 @@
return OP_CODE;
}
- public static void apply(WireBuffer buffer, int id) {
+ public static void apply(@NonNull WireBuffer buffer, int id) {
buffer.start(OP_CODE);
buffer.writeInt(id);
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Canvas Operations", OP_CODE, CLASS_NAME)
.description("Intersect the current clip with the path")
.field(DocumentedOperation.INT, "id", "id of the path");
}
@Override
- public void paint(PaintContext context) {
+ public void paint(@NonNull PaintContext context) {
context.clipPath(mId, mRegionOp);
}
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/ClipRect.java b/core/java/com/android/internal/widget/remotecompose/core/operations/ClipRect.java
index b101bfb..df54fb1 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/ClipRect.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/ClipRect.java
@@ -15,6 +15,8 @@
*/
package com.android.internal.widget.remotecompose.core.operations;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.PaintContext;
@@ -29,7 +31,7 @@
public static final int OP_CODE = Operations.CLIP_RECT;
public static final String CLASS_NAME = "ClipRect";
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
Maker m = ClipRect::new;
read(m, buffer, operations);
}
@@ -38,16 +40,17 @@
return OP_CODE;
}
+ @NonNull
public static String name() {
return CLASS_NAME;
}
@Override
- protected void write(WireBuffer buffer, float v1, float v2, float v3, float v4) {
+ protected void write(@NonNull WireBuffer buffer, float v1, float v2, float v3, float v4) {
apply(buffer, v1, v2, v3, v4);
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Expressions Operations", OP_CODE, CLASS_NAME)
.description("Intersect the current clip with rectangle")
.field(
@@ -74,7 +77,7 @@
}
@Override
- public void paint(PaintContext context) {
+ public void paint(@NonNull PaintContext context) {
context.clipRect(mX1, mY1, mX2, mY2);
}
@@ -87,7 +90,7 @@
* @param x2 end x of the DrawOval
* @param y2 end y of the DrawOval
*/
- public static void apply(WireBuffer buffer, float x1, float y1, float x2, float y2) {
+ public static void apply(@NonNull WireBuffer buffer, float x1, float y1, float x2, float y2) {
write(buffer, OP_CODE, x1, y1, x2, y2);
}
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/ColorConstant.java b/core/java/com/android/internal/widget/remotecompose/core/operations/ColorConstant.java
index 19d80da..929c9a60 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/ColorConstant.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/ColorConstant.java
@@ -17,6 +17,8 @@
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.RemoteContext;
@@ -39,15 +41,17 @@
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(buffer, mColorId, mColor);
}
+ @NonNull
@Override
public String toString() {
return "ColorConstant[" + mColorId + "] = " + Utils.colorInt(mColor) + "";
}
+ @NonNull
public static String name() {
return CLASS_NAME;
}
@@ -63,19 +67,19 @@
* @param colorId
* @param color
*/
- public static void apply(WireBuffer buffer, int colorId, int color) {
+ public static void apply(@NonNull WireBuffer buffer, int colorId, int color) {
buffer.start(OP_CODE);
buffer.writeInt(colorId);
buffer.writeInt(color);
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int colorId = buffer.readInt();
int color = buffer.readInt();
operations.add(new ColorConstant(colorId, color));
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Expressions Operations", OP_CODE, CLASS_NAME)
.description("Define a Color")
.field(DocumentedOperation.INT, "id", "Id of the color")
@@ -83,10 +87,11 @@
}
@Override
- public void apply(RemoteContext context) {
+ public void apply(@NonNull RemoteContext context) {
context.loadColor(mColorId, mColor);
}
+ @NonNull
@Override
public String deepToString(String indent) {
return indent + toString();
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/ColorExpression.java b/core/java/com/android/internal/widget/remotecompose/core/operations/ColorExpression.java
index b6041ea..3d840c5 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/ColorExpression.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/ColorExpression.java
@@ -18,6 +18,8 @@
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.FLOAT;
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.RemoteContext;
@@ -94,7 +96,7 @@
}
@Override
- public void updateVariables(RemoteContext context) {
+ public void updateVariables(@NonNull RemoteContext context) {
if (mMode == 4) {
if (Float.isNaN(mHue)) {
mOutHue = context.getFloat(Utils.idFromNan(mHue));
@@ -118,7 +120,7 @@
}
@Override
- public void registerListening(RemoteContext context) {
+ public void registerListening(@NonNull RemoteContext context) {
if (mMode == 4) {
if (Float.isNaN(mHue)) {
context.listensTo(Utils.idFromNan(mHue), this);
@@ -143,7 +145,7 @@
}
@Override
- public void apply(RemoteContext context) {
+ public void apply(@NonNull RemoteContext context) {
if (mMode == 4) {
context.loadColor(
mId, (mAlpha << 24) | (0xFFFFFF & Utils.hsvToRgb(mOutHue, mOutSat, mOutValue)));
@@ -164,11 +166,12 @@
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
int mode = mMode | (mAlpha << 16);
apply(buffer, mId, mode, mColor1, mColor2, mTween);
}
+ @NonNull
@Override
public String toString() {
if (mMode == 4) {
@@ -196,6 +199,7 @@
+ ")";
}
+ @NonNull
public static String name() {
return CLASS_NAME;
}
@@ -215,7 +219,7 @@
* @param tween
*/
public static void apply(
- WireBuffer buffer, int id, int mode, int color1, int color2, float tween) {
+ @NonNull WireBuffer buffer, int id, int mode, int color1, int color2, float tween) {
buffer.start(OP_CODE);
buffer.writeInt(id);
buffer.writeInt(mode);
@@ -224,7 +228,7 @@
buffer.writeFloat(tween);
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int id = buffer.readInt();
int mode = buffer.readInt();
int color1 = buffer.readInt();
@@ -234,7 +238,7 @@
operations.add(new ColorExpression(id, mode, color1, color2, tween));
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Expressions Operations", OP_CODE, CLASS_NAME)
.description("A Color defined by an expression")
.field(DocumentedOperation.INT, "id", "Id of the color")
@@ -249,6 +253,7 @@
.field(FLOAT, "tween", "32 bit ARGB color");
}
+ @NonNull
@Override
public String deepToString(String indent) {
return indent + toString();
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/ComponentValue.java b/core/java/com/android/internal/widget/remotecompose/core/operations/ComponentValue.java
index 9929720..142c97b2 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/ComponentValue.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/ComponentValue.java
@@ -17,6 +17,9 @@
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.RemoteContext;
@@ -43,10 +46,12 @@
return OP_CODE;
}
+ @NonNull
public static String name() {
return CLASS_NAME;
}
+ @NonNull
@Override
public String toString() {
return CLASS_NAME + "(" + mType + ", " + mComponentID + ", " + mValueId + ")";
@@ -65,7 +70,7 @@
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(buffer, mType, mComponentID, mValueId);
}
@@ -74,7 +79,7 @@
// Nothing
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int type = buffer.readInt();
int componentId = buffer.readInt();
int valueId = buffer.readInt();
@@ -82,7 +87,7 @@
operations.add(op);
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Expressions Operations", OP_CODE, CLASS_NAME)
.description("Encode a component-related value (eg its width, height etc.)")
.field(
@@ -111,20 +116,21 @@
* @param componentId component id to reference
* @param valueId remote float used to represent the component value
*/
- public static void apply(WireBuffer buffer, int type, int componentId, int valueId) {
+ public static void apply(@NonNull WireBuffer buffer, int type, int componentId, int valueId) {
buffer.start(OP_CODE);
buffer.writeInt(type);
buffer.writeInt(componentId);
buffer.writeInt(valueId);
}
+ @Nullable
@Override
public String deepToString(String indent) {
return null;
}
@Override
- public void serializeToString(int indent, StringSerializer serializer) {
+ public void serializeToString(int indent, @NonNull StringSerializer serializer) {
String type = "WIDTH";
if (mType == HEIGHT) {
type = "HEIGHT";
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DataListFloat.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DataListFloat.java
index 0075869..ba02b91 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/DataListFloat.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DataListFloat.java
@@ -18,6 +18,8 @@
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.FLOAT_ARRAY;
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.RemoteContext;
@@ -48,7 +50,7 @@
}
@Override
- public void registerListening(RemoteContext context) {
+ public void registerListening(@NonNull RemoteContext context) {
context.addCollection(mId, this);
for (float value : mValues) {
if (Utils.isVariable(value)) {
@@ -58,16 +60,17 @@
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(buffer, mId, mValues);
}
+ @NonNull
@Override
public String toString() {
return "DataListFloat[" + Utils.idString(mId) + "] " + Arrays.toString(mValues);
}
- public static void apply(WireBuffer buffer, int id, float[] values) {
+ public static void apply(@NonNull WireBuffer buffer, int id, @NonNull float[] values) {
buffer.start(OP_CODE);
buffer.writeInt(id);
buffer.writeInt(values.length);
@@ -76,7 +79,7 @@
}
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int id = buffer.readInt();
int len = buffer.readInt();
if (len > MAX_FLOAT_ARRAY) {
@@ -90,7 +93,7 @@
operations.add(data);
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Data Operations", OP_CODE, CLASS_NAME)
.description("a list of Floats")
.field(DocumentedOperation.INT, "id", "id the array (2xxxxx)")
@@ -98,13 +101,14 @@
.field(FLOAT_ARRAY, "values", "length", "array of floats");
}
+ @NonNull
@Override
public String deepToString(String indent) {
return indent + toString();
}
@Override
- public void apply(RemoteContext context) {
+ public void apply(@NonNull RemoteContext context) {
context.addCollection(mId, this);
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DataListIds.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DataListIds.java
index c43dab4..b9820f8 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/DataListIds.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DataListIds.java
@@ -18,6 +18,8 @@
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT;
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT_ARRAY;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.RemoteContext;
@@ -49,16 +51,17 @@
public void registerListening(RemoteContext context) {}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(buffer, mId, mIds);
}
+ @NonNull
@Override
public String toString() {
return "map[" + Utils.idString(mId) + "] \"" + Arrays.toString(mIds) + "\"";
}
- public static void apply(WireBuffer buffer, int id, int[] ids) {
+ public static void apply(@NonNull WireBuffer buffer, int id, @NonNull int[] ids) {
buffer.start(OP_CODE);
buffer.writeInt(id);
buffer.writeInt(ids.length);
@@ -67,7 +70,7 @@
}
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int id = buffer.readInt();
int len = buffer.readInt();
if (len > MAX_LIST) {
@@ -81,7 +84,7 @@
operations.add(data);
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Data Operations", OP_CODE, CLASS_NAME)
.description("a list of id's")
.field(DocumentedOperation.INT, "id", "id the array")
@@ -89,13 +92,14 @@
.field(INT_ARRAY, "ids[n]", "length", "ids of other variables");
}
+ @NonNull
@Override
public String deepToString(String indent) {
return indent + toString();
}
@Override
- public void apply(RemoteContext context) {
+ public void apply(@NonNull RemoteContext context) {
context.addCollection(mId, this);
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DataMapIds.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DataMapIds.java
index 75db29d..fb559bb 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/DataMapIds.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DataMapIds.java
@@ -18,6 +18,8 @@
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT;
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.UTF8;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.RemoteContext;
@@ -64,10 +66,11 @@
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(buffer, mId, mDataMap.mNames, mDataMap.mTypes, mDataMap.mIds);
}
+ @NonNull
@Override
public String toString() {
StringBuilder builder = new StringBuilder("DataMapIds[" + Utils.idString(mId) + "] ");
@@ -84,7 +87,8 @@
return builder.toString();
}
- public static void apply(WireBuffer buffer, int id, String[] names, byte[] type, int[] ids) {
+ public static void apply(
+ @NonNull WireBuffer buffer, int id, @NonNull String[] names, byte[] type, int[] ids) {
buffer.start(OP_CODE);
buffer.writeInt(id);
buffer.writeInt(names.length);
@@ -95,7 +99,7 @@
}
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int id = buffer.readInt();
int len = buffer.readInt();
if (len > MAX_MAP) {
@@ -113,7 +117,7 @@
operations.add(data);
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Data Operations", OP_CODE, CLASS_NAME)
.description("Encode a collection of name id pairs")
.field(INT, "id", "id the array")
@@ -122,13 +126,14 @@
.field(UTF8, "id[0]", "length", "path encoded as floats");
}
+ @NonNull
@Override
public String deepToString(String indent) {
return indent + toString();
}
@Override
- public void apply(RemoteContext context) {
+ public void apply(@NonNull RemoteContext context) {
context.putDataMap(mId, mDataMap);
}
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawArc.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawArc.java
index e078307..629f786 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawArc.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawArc.java
@@ -15,6 +15,8 @@
*/
package com.android.internal.widget.remotecompose.core.operations;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.PaintContext;
@@ -28,7 +30,7 @@
public static final int OP_CODE = Operations.DRAW_ARC;
private static final String CLASS_NAME = "DrawArc";
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
Maker m = DrawArc::new;
read(m, buffer, operations);
}
@@ -49,7 +51,13 @@
* @param v6 Sweep angle (in degrees) measured clockwise
*/
public static void apply(
- WireBuffer buffer, float v1, float v2, float v3, float v4, float v5, float v6) {
+ @NonNull WireBuffer buffer,
+ float v1,
+ float v2,
+ float v3,
+ float v4,
+ float v5,
+ float v6) {
buffer.start(OP_CODE);
buffer.writeFloat(v1);
buffer.writeFloat(v2);
@@ -61,11 +69,17 @@
@Override
protected void write(
- WireBuffer buffer, float v1, float v2, float v3, float v4, float v5, float v6) {
+ @NonNull WireBuffer buffer,
+ float v1,
+ float v2,
+ float v3,
+ float v4,
+ float v5,
+ float v6) {
apply(buffer, v1, v2, v3, v4, v5, v6);
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Canvas Operations", OP_CODE, CLASS_NAME)
.description(
"Draw the specified arc"
@@ -90,7 +104,7 @@
}
@Override
- public void paint(PaintContext context) {
+ public void paint(@NonNull PaintContext context) {
context.drawArc(mV1, mV2, mV3, mV4, mV5, mV6);
}
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBase2.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBase2.java
index c678cc4..984599e 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBase2.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBase2.java
@@ -17,6 +17,9 @@
import static com.android.internal.widget.remotecompose.core.operations.Utils.floatToString;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.PaintOperation;
import com.android.internal.widget.remotecompose.core.RemoteContext;
@@ -27,7 +30,7 @@
/** Base class for commands that take 3 float */
public abstract class DrawBase2 extends PaintOperation implements VariableSupport {
- protected String mName = "DrawRectBase";
+ @NonNull protected String mName = "DrawRectBase";
float mV1;
float mV2;
float mValue1;
@@ -41,13 +44,13 @@
}
@Override
- public void updateVariables(RemoteContext context) {
+ public void updateVariables(@NonNull RemoteContext context) {
mV1 = Float.isNaN(mValue1) ? context.getFloat(Utils.idFromNan(mValue1)) : mValue1;
mV2 = Float.isNaN(mValue2) ? context.getFloat(Utils.idFromNan(mValue2)) : mValue2;
}
@Override
- public void registerListening(RemoteContext context) {
+ public void registerListening(@NonNull RemoteContext context) {
if (Float.isNaN(mValue1)) {
context.listensTo(Utils.idFromNan(mValue1), this);
}
@@ -67,12 +70,14 @@
DrawBase2 create(float v1, float v2);
}
+ @NonNull
@Override
public String toString() {
return mName + " " + floatToString(mV1) + " " + floatToString(mV2);
}
- public static void read(Maker maker, WireBuffer buffer, List<Operation> operations) {
+ public static void read(
+ @NonNull Maker maker, @NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
float v1 = buffer.readFloat();
float v2 = buffer.readFloat();
@@ -87,6 +92,7 @@
* @param y1
* @return
*/
+ @Nullable
public Operation construct(float x1, float y1) {
return null;
}
@@ -99,7 +105,7 @@
* @param x1
* @param y1
*/
- protected static void write(WireBuffer buffer, int opCode, float x1, float y1) {
+ protected static void write(@NonNull WireBuffer buffer, int opCode, float x1, float y1) {
buffer.start(opCode);
buffer.writeFloat(x1);
buffer.writeFloat(y1);
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBase3.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBase3.java
index e1108e9..825da52 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBase3.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBase3.java
@@ -17,6 +17,9 @@
import static com.android.internal.widget.remotecompose.core.operations.Utils.floatToString;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.PaintOperation;
import com.android.internal.widget.remotecompose.core.RemoteContext;
@@ -28,7 +31,7 @@
/** Base class for commands that take 3 float */
public abstract class DrawBase3 extends PaintOperation implements VariableSupport {
- protected String mName = "DrawRectBase";
+ @NonNull protected String mName = "DrawRectBase";
float mV1;
float mV2;
float mV3;
@@ -47,14 +50,14 @@
}
@Override
- public void updateVariables(RemoteContext context) {
+ public void updateVariables(@NonNull RemoteContext context) {
mV1 = Utils.isVariable(mValue1) ? context.getFloat(Utils.idFromNan(mValue1)) : mValue1;
mV2 = Utils.isVariable(mValue2) ? context.getFloat(Utils.idFromNan(mValue2)) : mValue2;
mV3 = Utils.isVariable(mValue3) ? context.getFloat(Utils.idFromNan(mValue3)) : mValue3;
}
@Override
- public void registerListening(RemoteContext context) {
+ public void registerListening(@NonNull RemoteContext context) {
if (Utils.isVariable(mValue1)) {
context.listensTo(Utils.idFromNan(mValue1), this);
}
@@ -77,6 +80,7 @@
DrawBase3 create(float v1, float v2, float v3);
}
+ @NonNull
@Override
public String toString() {
return mName
@@ -88,7 +92,8 @@
+ floatToString(mV3);
}
- public static void read(Maker maker, WireBuffer buffer, List<Operation> operations) {
+ public static void read(
+ @NonNull Maker maker, @NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
float v1 = buffer.readFloat();
float v2 = buffer.readFloat();
float v3 = buffer.readFloat();
@@ -104,6 +109,7 @@
* @param x2
* @return
*/
+ @Nullable
public Operation construct(float x1, float y1, float x2) {
return null;
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBase4.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBase4.java
index 09f0df9..a23bcb9 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBase4.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBase4.java
@@ -17,6 +17,9 @@
import static com.android.internal.widget.remotecompose.core.operations.Utils.floatToString;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.PaintOperation;
import com.android.internal.widget.remotecompose.core.RemoteContext;
@@ -27,7 +30,7 @@
/** Base class for draw commands that take 4 floats */
public abstract class DrawBase4 extends PaintOperation implements VariableSupport {
- protected String mName = "DrawRectBase";
+ @NonNull protected String mName = "DrawRectBase";
protected float mX1;
protected float mY1;
protected float mX2;
@@ -50,7 +53,7 @@
}
@Override
- public void updateVariables(RemoteContext context) {
+ public void updateVariables(@NonNull RemoteContext context) {
mX1 = Float.isNaN(mX1Value) ? context.getFloat(Utils.idFromNan(mX1Value)) : mX1Value;
mY1 = Float.isNaN(mY1Value) ? context.getFloat(Utils.idFromNan(mY1Value)) : mY1Value;
mX2 = Float.isNaN(mX2Value) ? context.getFloat(Utils.idFromNan(mX2Value)) : mX2Value;
@@ -58,7 +61,7 @@
}
@Override
- public void registerListening(RemoteContext context) {
+ public void registerListening(@NonNull RemoteContext context) {
if (Float.isNaN(mX1Value)) {
context.listensTo(Utils.idFromNan(mX1Value), this);
}
@@ -84,6 +87,7 @@
DrawBase4 create(float v1, float v2, float v3, float v4);
}
+ @NonNull
@Override
public String toString() {
return mName
@@ -97,7 +101,8 @@
+ floatToString(mY2Value, mY2);
}
- public static void read(Maker maker, WireBuffer buffer, List<Operation> operations) {
+ public static void read(
+ @NonNull Maker maker, @NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
float v1 = buffer.readFloat();
float v2 = buffer.readFloat();
float v3 = buffer.readFloat();
@@ -116,6 +121,7 @@
* @param y2
* @return
*/
+ @Nullable
public Operation construct(float x1, float y1, float x2, float y2) {
return null;
}
@@ -131,7 +137,7 @@
* @param y2
*/
protected static void write(
- WireBuffer buffer, int opCode, float x1, float y1, float x2, float y2) {
+ @NonNull WireBuffer buffer, int opCode, float x1, float y1, float x2, float y2) {
buffer.start(opCode);
buffer.writeFloat(x1);
buffer.writeFloat(y1);
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBase6.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBase6.java
index e071d5f..68c9f8c 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBase6.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBase6.java
@@ -15,6 +15,9 @@
*/
package com.android.internal.widget.remotecompose.core.operations;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.PaintOperation;
import com.android.internal.widget.remotecompose.core.RemoteContext;
@@ -25,7 +28,7 @@
/** Base class for draw commands the take 6 floats */
public abstract class DrawBase6 extends PaintOperation implements VariableSupport {
- protected String mName = "DrawRectBase";
+ @NonNull protected String mName = "DrawRectBase";
float mV1;
float mV2;
float mV3;
@@ -56,7 +59,7 @@
}
@Override
- public void updateVariables(RemoteContext context) {
+ public void updateVariables(@NonNull RemoteContext context) {
mV1 = Float.isNaN(mValue1) ? context.getFloat(Utils.idFromNan(mValue1)) : mValue1;
mV2 = Float.isNaN(mValue2) ? context.getFloat(Utils.idFromNan(mValue2)) : mValue2;
mV3 = Float.isNaN(mValue3) ? context.getFloat(Utils.idFromNan(mValue3)) : mValue3;
@@ -66,7 +69,7 @@
}
@Override
- public void registerListening(RemoteContext context) {
+ public void registerListening(@NonNull RemoteContext context) {
if (Float.isNaN(mValue1)) {
context.listensTo(Utils.idFromNan(mValue1), this);
}
@@ -95,6 +98,7 @@
protected abstract void write(
WireBuffer buffer, float v1, float v2, float v3, float v4, float v5, float v6);
+ @NonNull
@Override
public String toString() {
return mName
@@ -112,7 +116,8 @@
DrawBase6 create(float v1, float v2, float v3, float v4, float v5, float v6);
}
- public static void read(Maker build, WireBuffer buffer, List<Operation> operations) {
+ public static void read(
+ @NonNull Maker build, @NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
float sv1 = buffer.readFloat();
float sv2 = buffer.readFloat();
float sv3 = buffer.readFloat();
@@ -135,10 +140,12 @@
* @param v6
* @return
*/
+ @Nullable
public Operation construct(float v1, float v2, float v3, float v4, float v5, float v6) {
return null;
}
+ @NonNull
public static String name() {
return "DrawBase6";
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmap.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmap.java
index 0b43fd2..9c23c95 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmap.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmap.java
@@ -18,6 +18,8 @@
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.FLOAT;
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.PaintContext;
@@ -54,7 +56,7 @@
}
@Override
- public void updateVariables(RemoteContext context) {
+ public void updateVariables(@NonNull RemoteContext context) {
mOutputLeft = Float.isNaN(mLeft) ? context.getFloat(Utils.idFromNan(mLeft)) : mLeft;
mOutputTop = Float.isNaN(mTop) ? context.getFloat(Utils.idFromNan(mTop)) : mTop;
mOutputRight = Float.isNaN(mRight) ? context.getFloat(Utils.idFromNan(mRight)) : mRight;
@@ -62,7 +64,7 @@
}
@Override
- public void registerListening(RemoteContext context) {
+ public void registerListening(@NonNull RemoteContext context) {
if (Float.isNaN(mLeft)) {
context.listensTo(Utils.idFromNan(mLeft), this);
}
@@ -78,10 +80,11 @@
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(buffer, mId, mLeft, mTop, mRight, mBottom, mDescriptionId);
}
+ @NonNull
@Override
public String toString() {
return "DrawBitmap (desc="
@@ -97,7 +100,7 @@
+ ";";
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int id = buffer.readInt();
float sLeft = buffer.readFloat();
float srcTop = buffer.readFloat();
@@ -109,6 +112,7 @@
operations.add(op);
}
+ @NonNull
public static String name() {
return CLASS_NAME;
}
@@ -118,7 +122,7 @@
}
public static void apply(
- WireBuffer buffer,
+ @NonNull WireBuffer buffer,
int id,
float left,
float top,
@@ -134,7 +138,7 @@
buffer.writeInt(descriptionId);
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Draw Operations", OP_CODE, CLASS_NAME)
.description("Draw a bitmap")
.field(INT, "id", "id of float")
@@ -146,7 +150,7 @@
}
@Override
- public void paint(PaintContext context) {
+ public void paint(@NonNull PaintContext context) {
context.drawBitmap(mId, mOutputLeft, mOutputTop, mOutputRight, mOutputBottom);
}
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmapInt.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmapInt.java
index fc74827..da9fe24 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmapInt.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmapInt.java
@@ -15,6 +15,8 @@
*/
package com.android.internal.widget.remotecompose.core.operations;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.PaintContext;
@@ -64,7 +66,7 @@
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(
buffer,
mImageId,
@@ -79,6 +81,7 @@
mContentDescId);
}
+ @NonNull
@Override
public String toString() {
return "DRAW_BITMAP_INT "
@@ -103,6 +106,7 @@
+ ";";
}
+ @NonNull
public static String name() {
return CLASS_NAME;
}
@@ -112,7 +116,7 @@
}
public static void apply(
- WireBuffer buffer,
+ @NonNull WireBuffer buffer,
int imageId,
int srcLeft,
int srcTop,
@@ -136,7 +140,7 @@
buffer.writeInt(cdId);
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int imageId = buffer.readInt();
int sLeft = buffer.readInt();
int srcTop = buffer.readInt();
@@ -155,7 +159,7 @@
operations.add(op);
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Draw Operations", OP_CODE, CLASS_NAME)
.description("Draw a bitmap using integer coordinates")
.field(DocumentedOperation.INT, "id", "id of bitmap")
@@ -171,7 +175,7 @@
}
@Override
- public void paint(PaintContext context) {
+ public void paint(@NonNull PaintContext context) {
context.drawBitmap(
mImageId,
mSrcLeft,
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmapScaled.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmapScaled.java
index 22742c6..e20bcd2 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmapScaled.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmapScaled.java
@@ -15,6 +15,8 @@
*/
package com.android.internal.widget.remotecompose.core.operations;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.PaintContext;
@@ -45,7 +47,7 @@
float mScaleFactor, mOutScaleFactor;
int mScaleType;
- ImageScaling mScaling = new ImageScaling();
+ @NonNull ImageScaling mScaling = new ImageScaling();
public static final int SCALE_NONE = ImageScaling.SCALE_NONE;
public static final int SCALE_INSIDE = ImageScaling.SCALE_INSIDE;
public static final int SCALE_FILL_WIDTH = ImageScaling.SCALE_FILL_WIDTH;
@@ -83,7 +85,7 @@
}
@Override
- public void updateVariables(RemoteContext context) {
+ public void updateVariables(@NonNull RemoteContext context) {
mOutSrcLeft =
Float.isNaN(mSrcLeft) ? context.getFloat(Utils.idFromNan(mSrcLeft)) : mSrcLeft;
mOutSrcTop = Float.isNaN(mSrcTop) ? context.getFloat(Utils.idFromNan(mSrcTop)) : mSrcTop;
@@ -109,7 +111,7 @@
}
@Override
- public void registerListening(RemoteContext context) {
+ public void registerListening(@NonNull RemoteContext context) {
register(context, mSrcLeft);
register(context, mSrcTop);
register(context, mSrcRight);
@@ -121,12 +123,13 @@
register(context, mScaleFactor);
}
- private void register(RemoteContext context, float value) {
+ private void register(@NonNull RemoteContext context, float value) {
if (Float.isNaN(value)) {
context.listensTo(Utils.idFromNan(value), this);
}
}
+ @NonNull
static String str(float v) {
String s = " " + (int) v;
return s.substring(s.length() - 3);
@@ -140,7 +143,7 @@
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(
buffer,
mImageId,
@@ -157,6 +160,7 @@
mContentDescId);
}
+ @NonNull
@Override
public String toString() {
return "DrawBitmapScaled "
@@ -185,6 +189,7 @@
+ Utils.floatToString(mScaleFactor, mOutScaleFactor);
}
+ @NonNull
public static String name() {
return CLASS_NAME;
}
@@ -194,7 +199,7 @@
}
public static void apply(
- WireBuffer buffer,
+ @NonNull WireBuffer buffer,
int imageId,
float srcLeft,
float srcTop,
@@ -225,7 +230,7 @@
buffer.writeInt(cdId);
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int imageId = buffer.readInt();
float sLeft = buffer.readFloat();
@@ -258,7 +263,7 @@
operations.add(op);
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Draw Operations", OP_CODE, CLASS_NAME)
.description("Draw a bitmap using integer coordinates")
.field(DocumentedOperation.INT, "id", "id of bitmap")
@@ -289,7 +294,7 @@
// }
@Override
- public void paint(PaintContext context) {
+ public void paint(@NonNull PaintContext context) {
mScaling.setup(
mOutSrcLeft,
mOutSrcTop,
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawCircle.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawCircle.java
index 04f095a..11bd49a 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawCircle.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawCircle.java
@@ -15,6 +15,8 @@
*/
package com.android.internal.widget.remotecompose.core.operations;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.PaintContext;
@@ -28,7 +30,7 @@
private static final int OP_CODE = Operations.DRAW_CIRCLE;
private static final String CLASS_NAME = "DrawCircle";
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
Maker m = DrawCircle::new;
read(m, buffer, operations);
}
@@ -37,11 +39,12 @@
return OP_CODE;
}
+ @NonNull
public static String name() {
return CLASS_NAME;
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Canvas Operations", OP_CODE, CLASS_NAME)
.description("Draw a Circle")
.field(
@@ -56,7 +59,7 @@
}
@Override
- protected void write(WireBuffer buffer, float v1, float v2, float v3) {
+ protected void write(@NonNull WireBuffer buffer, float v1, float v2, float v3) {
apply(buffer, v1, v2, v3);
}
@@ -66,7 +69,7 @@
}
@Override
- public void paint(PaintContext context) {
+ public void paint(@NonNull PaintContext context) {
context.drawCircle(mV1, mV2, mV3);
}
@@ -78,7 +81,7 @@
* @param y1
* @param x2
*/
- public static void apply(WireBuffer buffer, float x1, float y1, float x2) {
+ public static void apply(@NonNull WireBuffer buffer, float x1, float y1, float x2) {
buffer.start(OP_CODE);
buffer.writeFloat(x1);
buffer.writeFloat(y1);
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawLine.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawLine.java
index dacbb03..7310a9d 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawLine.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawLine.java
@@ -15,6 +15,8 @@
*/
package com.android.internal.widget.remotecompose.core.operations;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.PaintContext;
@@ -30,7 +32,7 @@
private static final int OP_CODE = Operations.DRAW_LINE;
private static final String CLASS_NAME = "DrawLine";
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
Maker m = DrawLine::new;
read(m, buffer, operations);
}
@@ -39,11 +41,12 @@
return OP_CODE;
}
+ @NonNull
public static String name() {
return CLASS_NAME;
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Canvas Operations", OP_CODE, CLASS_NAME)
.description("Draw a line segment")
.field(
@@ -65,7 +68,7 @@
}
@Override
- protected void write(WireBuffer buffer, float v1, float v2, float v3, float v4) {
+ protected void write(@NonNull WireBuffer buffer, float v1, float v2, float v3, float v4) {
apply(buffer, v1, v2, v3, v4);
}
@@ -75,7 +78,7 @@
}
@Override
- public void paint(PaintContext context) {
+ public void paint(@NonNull PaintContext context) {
context.drawLine(mX1, mY1, mX2, mY2);
}
@@ -88,12 +91,12 @@
* @param x2 end x of the line
* @param y2 end y of the line
*/
- public static void apply(WireBuffer buffer, float x1, float y1, float x2, float y2) {
+ public static void apply(@NonNull WireBuffer buffer, float x1, float y1, float x2, float y2) {
write(buffer, OP_CODE, x1, y1, x2, y2);
}
@Override
- public void serializeToString(int indent, StringSerializer serializer) {
+ public void serializeToString(int indent, @NonNull StringSerializer serializer) {
String x1 = "" + mX1;
if (Float.isNaN(mX1Value)) {
x1 = "[" + Utils.idFromNan(mX1Value) + " = " + mX1 + "]";
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawOval.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawOval.java
index 5d498e8..aa5116e 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawOval.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawOval.java
@@ -15,6 +15,8 @@
*/
package com.android.internal.widget.remotecompose.core.operations;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.PaintContext;
@@ -28,7 +30,7 @@
private static final int OP_CODE = Operations.DRAW_OVAL;
private static final String CLASS_NAME = "DrawOval";
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
Maker m = DrawOval::new;
read(m, buffer, operations);
}
@@ -37,11 +39,12 @@
return OP_CODE;
}
+ @NonNull
public static String name() {
return CLASS_NAME;
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Canvas Operations", OP_CODE, CLASS_NAME)
.description("Draw the specified oval")
.field(DocumentedOperation.FLOAT, "left", "The left side of the oval")
@@ -51,12 +54,12 @@
}
@Override
- protected void write(WireBuffer buffer, float v1, float v2, float v3, float v4) {
+ protected void write(@NonNull WireBuffer buffer, float v1, float v2, float v3, float v4) {
apply(buffer, v1, v2, v3, v4);
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(buffer, mX1, mY1, mX2, mY2);
}
@@ -66,7 +69,7 @@
}
@Override
- public void paint(PaintContext context) {
+ public void paint(@NonNull PaintContext context) {
context.drawOval(mX1, mY1, mX2, mY2);
}
@@ -79,7 +82,7 @@
* @param x2 end x of the DrawOval
* @param y2 end y of the DrawOval
*/
- public static void apply(WireBuffer buffer, float x1, float y1, float x2, float y2) {
+ public static void apply(@NonNull WireBuffer buffer, float x1, float y1, float x2, float y2) {
write(buffer, OP_CODE, x1, y1, x2, y2);
}
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawPath.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawPath.java
index ccbf3d9..d35094b 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawPath.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawPath.java
@@ -15,6 +15,8 @@
*/
package com.android.internal.widget.remotecompose.core.operations;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.PaintContext;
@@ -38,21 +40,23 @@
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(buffer, mId);
}
+ @NonNull
@Override
public String toString() {
return "DrawPath " + "[" + mId + "]" + ", " + mStart + ", " + mEnd;
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int id = buffer.readInt();
DrawPath op = new DrawPath(id);
operations.add(op);
}
+ @NonNull
public static String name() {
return CLASS_NAME;
}
@@ -61,19 +65,19 @@
return Operations.DRAW_PATH;
}
- public static void apply(WireBuffer buffer, int id) {
+ public static void apply(@NonNull WireBuffer buffer, int id) {
buffer.start(Operations.DRAW_PATH);
buffer.writeInt(id);
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Draw Operations", OP_CODE, CLASS_NAME)
.description("Draw a bitmap using integer coordinates")
.field(DocumentedOperation.INT, "id", "id of path");
}
@Override
- public void paint(PaintContext context) {
+ public void paint(@NonNull PaintContext context) {
context.drawPath(mId, mStart, mEnd);
}
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawRect.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawRect.java
index 644011b..db7633c 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawRect.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawRect.java
@@ -15,6 +15,8 @@
*/
package com.android.internal.widget.remotecompose.core.operations;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.PaintContext;
@@ -29,7 +31,7 @@
private static final int OP_CODE = Operations.DRAW_RECT;
private static final String CLASS_NAME = "DrawRect";
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
Maker m = DrawRect::new;
read(m, buffer, operations);
}
@@ -38,11 +40,12 @@
return OP_CODE;
}
+ @NonNull
public static String name() {
return CLASS_NAME;
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Canvas Operations", OP_CODE, CLASS_NAME)
.description("Draw the specified rectangle")
.field(DocumentedOperation.FLOAT, "left", "The left side of the rectangle")
@@ -52,7 +55,7 @@
}
@Override
- protected void write(WireBuffer buffer, float v1, float v2, float v3, float v4) {
+ protected void write(@NonNull WireBuffer buffer, float v1, float v2, float v3, float v4) {
apply(buffer, v1, v2, v3, v4);
}
@@ -62,7 +65,7 @@
}
@Override
- public void paint(PaintContext context) {
+ public void paint(@NonNull PaintContext context) {
context.drawRect(mX1, mY1, mX2, mY2);
}
@@ -75,7 +78,7 @@
* @param x2 right x of the rect
* @param y2 bottom y of the rect
*/
- public static void apply(WireBuffer buffer, float x1, float y1, float x2, float y2) {
+ public static void apply(@NonNull WireBuffer buffer, float x1, float y1, float x2, float y2) {
write(buffer, OP_CODE, x1, y1, x2, y2);
}
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawRoundRect.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawRoundRect.java
index 64a3b28..c306e2b 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawRoundRect.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawRoundRect.java
@@ -15,6 +15,8 @@
*/
package com.android.internal.widget.remotecompose.core.operations;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.PaintContext;
@@ -29,7 +31,7 @@
private static final int OP_CODE = Operations.DRAW_ROUND_RECT;
private static final String CLASS_NAME = "DrawRoundRect";
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
Maker m = DrawRoundRect::new;
read(m, buffer, operations);
}
@@ -50,7 +52,13 @@
* @param v6 The y-radius of the oval used to round the corners
*/
public static void apply(
- WireBuffer buffer, float v1, float v2, float v3, float v4, float v5, float v6) {
+ @NonNull WireBuffer buffer,
+ float v1,
+ float v2,
+ float v3,
+ float v4,
+ float v5,
+ float v6) {
buffer.start(OP_CODE);
buffer.writeFloat(v1);
buffer.writeFloat(v2);
@@ -62,11 +70,17 @@
@Override
protected void write(
- WireBuffer buffer, float v1, float v2, float v3, float v4, float v5, float v6) {
+ @NonNull WireBuffer buffer,
+ float v1,
+ float v2,
+ float v3,
+ float v4,
+ float v5,
+ float v6) {
apply(buffer, v1, v2, v3, v4, v5, v6);
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Canvas Operations", OP_CODE, CLASS_NAME)
.description("Draw the specified round-rect")
.field(DocumentedOperation.FLOAT, "left", "The left side of the rect")
@@ -89,7 +103,7 @@
}
@Override
- public void paint(PaintContext context) {
+ public void paint(@NonNull PaintContext context) {
context.drawRoundRect(mV1, mV2, mV3, mV4, mV5, mV6);
}
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawSector.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawSector.java
index 3cb1916..3b60df7 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawSector.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawSector.java
@@ -15,6 +15,8 @@
*/
package com.android.internal.widget.remotecompose.core.operations;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.PaintContext;
@@ -28,7 +30,7 @@
public static final int OP_CODE = Operations.DRAW_SECTOR;
private static final String CLASS_NAME = "DrawSector";
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
Maker m = DrawSector::new;
read(m, buffer, operations);
}
@@ -49,7 +51,13 @@
* @param v6 Sweep angle (in degrees) measured clockwise
*/
public static void apply(
- WireBuffer buffer, float v1, float v2, float v3, float v4, float v5, float v6) {
+ @NonNull WireBuffer buffer,
+ float v1,
+ float v2,
+ float v3,
+ float v4,
+ float v5,
+ float v6) {
buffer.start(OP_CODE);
buffer.writeFloat(v1);
buffer.writeFloat(v2);
@@ -61,11 +69,17 @@
@Override
protected void write(
- WireBuffer buffer, float v1, float v2, float v3, float v4, float v5, float v6) {
+ @NonNull WireBuffer buffer,
+ float v1,
+ float v2,
+ float v3,
+ float v4,
+ float v5,
+ float v6) {
apply(buffer, v1, v2, v3, v4, v5, v6);
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Canvas Operations", OP_CODE, CLASS_NAME)
.description(
"Draw the specified sector (pie shape)"
@@ -90,7 +104,7 @@
}
@Override
- public void paint(PaintContext context) {
+ public void paint(@NonNull PaintContext context) {
context.drawSector(mV1, mV2, mV3, mV4, mV5, mV6);
}
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawText.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawText.java
index bcb7852..9c587ab 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawText.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawText.java
@@ -17,6 +17,8 @@
import static com.android.internal.widget.remotecompose.core.operations.Utils.floatToString;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.PaintContext;
@@ -64,13 +66,13 @@
}
@Override
- public void updateVariables(RemoteContext context) {
+ public void updateVariables(@NonNull RemoteContext context) {
mOutX = Float.isNaN(mX) ? context.getFloat(Utils.idFromNan(mX)) : mX;
mOutY = Float.isNaN(mY) ? context.getFloat(Utils.idFromNan(mY)) : mY;
}
@Override
- public void registerListening(RemoteContext context) {
+ public void registerListening(@NonNull RemoteContext context) {
if (Float.isNaN(mX)) {
context.listensTo(Utils.idFromNan(mX), this);
}
@@ -80,10 +82,11 @@
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(buffer, mTextID, mStart, mEnd, mContextStart, mContextEnd, mX, mY, mRtl);
}
+ @NonNull
@Override
public String toString() {
return "DrawTextRun ["
@@ -98,7 +101,7 @@
+ floatToString(mY, mOutY);
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int text = buffer.readInt();
int start = buffer.readInt();
int end = buffer.readInt();
@@ -112,6 +115,7 @@
operations.add(op);
}
+ @NonNull
public static String name() {
return CLASS_NAME;
}
@@ -134,7 +138,7 @@
* @param rtl is it Right to Left text
*/
public static void apply(
- WireBuffer buffer,
+ @NonNull WireBuffer buffer,
int textID,
int start,
int end,
@@ -154,7 +158,7 @@
buffer.writeBoolean(rtl);
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Draw Operations", id(), CLASS_NAME)
.description("Draw a run of text, all in a single direction")
.field(DocumentedOperation.INT, "textId", "id of bitmap")
@@ -177,7 +181,7 @@
}
@Override
- public void paint(PaintContext context) {
+ public void paint(@NonNull PaintContext context) {
context.drawTextRun(mTextID, mStart, mEnd, mContextStart, mContextEnd, mOutX, mOutY, mRtl);
}
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawTextAnchored.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawTextAnchored.java
index 95a8766..8b70181 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawTextAnchored.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawTextAnchored.java
@@ -15,6 +15,8 @@
*/
package com.android.internal.widget.remotecompose.core.operations;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.PaintContext;
@@ -57,7 +59,7 @@
}
@Override
- public void updateVariables(RemoteContext context) {
+ public void updateVariables(@NonNull RemoteContext context) {
mOutX = Float.isNaN(mX) ? context.getFloat(Utils.idFromNan(mX)) : mX;
mOutY = Float.isNaN(mY) ? context.getFloat(Utils.idFromNan(mY)) : mY;
mOutPanX = Float.isNaN(mPanX) ? context.getFloat(Utils.idFromNan(mPanX)) : mPanX;
@@ -65,7 +67,7 @@
}
@Override
- public void registerListening(RemoteContext context) {
+ public void registerListening(@NonNull RemoteContext context) {
if (Float.isNaN(mX)) {
context.listensTo(Utils.idFromNan(mX), this);
}
@@ -81,10 +83,11 @@
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(buffer, mTextID, mX, mY, mPanX, mPanY, mFlags);
}
+ @NonNull
@Override
public String toString() {
return "DrawTextAnchored ["
@@ -108,7 +111,7 @@
return Float.toString(v);
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int textID = buffer.readInt();
float x = buffer.readFloat();
float y = buffer.readFloat();
@@ -121,6 +124,7 @@
operations.add(op);
}
+ @NonNull
public static String name() {
return CLASS_NAME;
}
@@ -141,7 +145,13 @@
* @param flags Change the behaviour
*/
public static void apply(
- WireBuffer buffer, int textID, float x, float y, float panX, float panY, int flags) {
+ @NonNull WireBuffer buffer,
+ int textID,
+ float x,
+ float y,
+ float panX,
+ float panY,
+ int flags) {
buffer.start(OP_CODE);
buffer.writeInt(textID);
buffer.writeFloat(x);
@@ -151,7 +161,7 @@
buffer.writeInt(flags);
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Draw Operations", OP_CODE, CLASS_NAME)
.description("Draw text centered about an anchor point")
.field(DocumentedOperation.INT, "textId", "id of bitmap")
@@ -168,7 +178,7 @@
.field(DocumentedOperation.INT, "flags", "Change the behaviour");
}
- float[] mBounds = new float[4];
+ @NonNull float[] mBounds = new float[4];
private float getHorizontalOffset() {
// TODO scale TextSize / BaseTextSize;
@@ -188,7 +198,7 @@
}
@Override
- public void paint(PaintContext context) {
+ public void paint(@NonNull PaintContext context) {
int flags =
((mFlags & ANCHOR_MONOSPACE_MEASURE) != 0)
? PaintContext.TEXT_MEASURE_MONOSPACE_WIDTH
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawTextOnPath.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawTextOnPath.java
index aefd6f3..e90122b 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawTextOnPath.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawTextOnPath.java
@@ -15,6 +15,8 @@
*/
package com.android.internal.widget.remotecompose.core.operations;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.PaintContext;
@@ -46,7 +48,7 @@
}
@Override
- public void updateVariables(RemoteContext context) {
+ public void updateVariables(@NonNull RemoteContext context) {
mOutHOffset =
Float.isNaN(mHOffset) ? context.getFloat(Utils.idFromNan(mHOffset)) : mHOffset;
mOutVOffset =
@@ -54,7 +56,7 @@
}
@Override
- public void registerListening(RemoteContext context) {
+ public void registerListening(@NonNull RemoteContext context) {
if (Float.isNaN(mHOffset)) {
context.listensTo(Utils.idFromNan(mHOffset), this);
}
@@ -64,10 +66,11 @@
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(buffer, mTextId, mPathId, mHOffset, mVOffset);
}
+ @NonNull
@Override
public String toString() {
return "DrawTextOnPath ["
@@ -80,7 +83,7 @@
+ Utils.floatToString(mVOffset, mOutVOffset);
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int textId = buffer.readInt();
int pathId = buffer.readInt();
float vOffset = buffer.readFloat();
@@ -89,6 +92,7 @@
operations.add(op);
}
+ @NonNull
public static String name() {
return "DrawTextOnPath";
}
@@ -98,7 +102,7 @@
}
public static void apply(
- WireBuffer buffer, int textId, int pathId, float hOffset, float vOffset) {
+ @NonNull WireBuffer buffer, int textId, int pathId, float hOffset, float vOffset) {
buffer.start(OP_CODE);
buffer.writeInt(textId);
buffer.writeInt(pathId);
@@ -106,7 +110,7 @@
buffer.writeFloat(hOffset);
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Draw Operations", OP_CODE, CLASS_NAME)
.description("Draw text along path object")
.field(DocumentedOperation.INT, "textId", "id of the text")
@@ -116,7 +120,7 @@
}
@Override
- public void paint(PaintContext context) {
+ public void paint(@NonNull PaintContext context) {
context.drawTextOnPath(mTextId, mPathId, mOutHOffset, mOutVOffset);
}
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawTweenPath.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawTweenPath.java
index b6d45d9..0aaaf42 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawTweenPath.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawTweenPath.java
@@ -17,6 +17,8 @@
import static com.android.internal.widget.remotecompose.core.operations.Utils.floatToString;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.PaintContext;
@@ -50,14 +52,14 @@
}
@Override
- public void updateVariables(RemoteContext context) {
+ public void updateVariables(@NonNull RemoteContext context) {
mOutTween = Float.isNaN(mTween) ? context.getFloat(Utils.idFromNan(mTween)) : mTween;
mOutStart = Float.isNaN(mStart) ? context.getFloat(Utils.idFromNan(mStart)) : mStart;
mOutStop = Float.isNaN(mStop) ? context.getFloat(Utils.idFromNan(mStop)) : mStop;
}
@Override
- public void registerListening(RemoteContext context) {
+ public void registerListening(@NonNull RemoteContext context) {
if (Float.isNaN(mTween)) {
context.listensTo(Utils.idFromNan(mTween), this);
}
@@ -70,10 +72,11 @@
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(buffer, mPath1Id, mPath2Id, mTween, mStart, mStop);
}
+ @NonNull
@Override
public String toString() {
return "DrawTweenPath "
@@ -89,7 +92,7 @@
+ floatToString(mStop, mOutStop);
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int path1Id = buffer.readInt();
int path2Id = buffer.readInt();
float tween = buffer.readFloat();
@@ -99,6 +102,7 @@
operations.add(op);
}
+ @NonNull
public static String name() {
return "DrawTweenPath";
}
@@ -108,7 +112,12 @@
}
public static void apply(
- WireBuffer buffer, int path1Id, int path2Id, float tween, float start, float stop) {
+ @NonNull WireBuffer buffer,
+ int path1Id,
+ int path2Id,
+ float tween,
+ float start,
+ float stop) {
buffer.start(OP_CODE);
buffer.writeInt(path1Id);
buffer.writeInt(path2Id);
@@ -117,7 +126,7 @@
buffer.writeFloat(stop);
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Draw Operations", OP_CODE, CLASS_NAME)
.description("Draw text along path object")
.field(DocumentedOperation.INT, "pathId1", "id of path 1")
@@ -128,7 +137,7 @@
}
@Override
- public void paint(PaintContext context) {
+ public void paint(@NonNull PaintContext context) {
context.drawTweenPath(mPath1Id, mPath2Id, mOutTween, mOutStart, mOutStop);
}
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/FloatConstant.java b/core/java/com/android/internal/widget/remotecompose/core/operations/FloatConstant.java
index 765e150..89390ac 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/FloatConstant.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/FloatConstant.java
@@ -17,6 +17,8 @@
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.FLOAT;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.RemoteContext;
@@ -39,15 +41,17 @@
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(buffer, mTextId, mValue);
}
+ @NonNull
@Override
public String toString() {
return "FloatConstant[" + mTextId + "] = " + mValue;
}
+ @NonNull
public static String name() {
return CLASS_NAME;
}
@@ -63,20 +67,20 @@
* @param id the id
* @param value the value of the float
*/
- public static void apply(WireBuffer buffer, int id, float value) {
+ public static void apply(@NonNull WireBuffer buffer, int id, float value) {
buffer.start(OP_CODE);
buffer.writeInt(id);
buffer.writeFloat(value);
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int textId = buffer.readInt();
float value = buffer.readFloat();
operations.add(new FloatConstant(textId, value));
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Expressions Operations", OP_CODE, CLASS_NAME)
.description("A float and its associated id")
.field(DocumentedOperation.INT, "id", "id of float")
@@ -84,10 +88,11 @@
}
@Override
- public void apply(RemoteContext context) {
+ public void apply(@NonNull RemoteContext context) {
context.loadFloat(mTextId, mValue);
}
+ @NonNull
@Override
public String deepToString(String indent) {
return indent + toString();
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/FloatExpression.java b/core/java/com/android/internal/widget/remotecompose/core/operations/FloatExpression.java
index d717933..e1c6c25 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/FloatExpression.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/FloatExpression.java
@@ -20,6 +20,9 @@
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT;
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.SHORT;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.RemoteContext;
@@ -48,7 +51,7 @@
public float[] mPreCalcValue;
private float mLastChange = Float.NaN;
private float mLastCalculatedValue = Float.NaN;
- AnimatedFloatExpression mExp = new AnimatedFloatExpression();
+ @NonNull AnimatedFloatExpression mExp = new AnimatedFloatExpression();
public static final int MAX_EXPRESSION_SIZE = 32;
public FloatExpression(int id, float[] value, float[] animation) {
@@ -61,7 +64,7 @@
}
@Override
- public void updateVariables(RemoteContext context) {
+ public void updateVariables(@NonNull RemoteContext context) {
if (mPreCalcValue == null || mPreCalcValue.length != mSrcValue.length) {
mPreCalcValue = new float[mSrcValue.length];
}
@@ -107,7 +110,7 @@
}
@Override
- public void registerListening(RemoteContext context) {
+ public void registerListening(@NonNull RemoteContext context) {
for (float v : mSrcValue) {
if (Float.isNaN(v)
&& !AnimatedFloatExpression.isMathOperator(v)
@@ -118,7 +121,7 @@
}
@Override
- public void apply(RemoteContext context) {
+ public void apply(@NonNull RemoteContext context) {
updateVariables(context);
float t = context.getAnimationTime();
if (Float.isNaN(mLastChange)) {
@@ -135,10 +138,11 @@
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(buffer, mId, mSrcValue, mSrcAnimation);
}
+ @NonNull
@Override
public String toString() {
String[] labels = new String[mSrcValue.length];
@@ -161,6 +165,7 @@
+ ")";
}
+ @NonNull
public static String name() {
return CLASS_NAME;
}
@@ -177,7 +182,11 @@
* @param value the float expression array
* @param animation the animation expression array
*/
- public static void apply(WireBuffer buffer, int id, float[] value, float[] animation) {
+ public static void apply(
+ @NonNull WireBuffer buffer,
+ int id,
+ @NonNull float[] value,
+ @Nullable float[] animation) {
buffer.start(OP_CODE);
buffer.writeInt(id);
@@ -197,7 +206,7 @@
}
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int id = buffer.readInt();
int len = buffer.readInt();
int valueLen = len & 0xFFFF;
@@ -222,7 +231,7 @@
operations.add(new FloatExpression(id, values, animation));
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Expressions Operations", OP_CODE, CLASS_NAME)
.description("A Float expression")
.field(DocumentedOperation.INT, "id", "The id of the Color")
@@ -245,6 +254,7 @@
.field(FLOAT, "wrapValue", "> [Wrap value] ");
}
+ @NonNull
@Override
public String deepToString(String indent) {
return indent + toString();
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/Header.java b/core/java/com/android/internal/widget/remotecompose/core/operations/Header.java
index 4f8516f..1979bc5 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/Header.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/Header.java
@@ -18,6 +18,8 @@
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT;
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.LONG;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.RemoteComposeOperation;
@@ -80,10 +82,11 @@
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(buffer, mWidth, mHeight, mDensity, mCapabilities);
}
+ @NonNull
@Override
public String toString() {
return "HEADER v"
@@ -102,15 +105,17 @@
}
@Override
- public void apply(RemoteContext context) {
+ public void apply(@NonNull RemoteContext context) {
context.header(mMajorVersion, mMinorVersion, mPatchVersion, mWidth, mHeight, mCapabilities);
}
+ @NonNull
@Override
public String deepToString(String indent) {
return toString();
}
+ @NonNull
public static String name() {
return CLASS_NAME;
}
@@ -120,7 +125,7 @@
}
public static void apply(
- WireBuffer buffer, int width, int height, float density, long capabilities) {
+ @NonNull WireBuffer buffer, int width, int height, float density, long capabilities) {
buffer.start(OP_CODE);
buffer.writeInt(MAJOR_VERSION); // major version number of the protocol
buffer.writeInt(MINOR_VERSION); // minor version number of the protocol
@@ -131,7 +136,7 @@
buffer.writeLong(capabilities);
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int majorVersion = buffer.readInt();
int minorVersion = buffer.readInt();
int patchVersion = buffer.readInt();
@@ -152,7 +157,7 @@
operations.add(header);
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Protocol Operations", OP_CODE, CLASS_NAME)
.description(
"Document metadata, containing the version,"
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/IntegerExpression.java b/core/java/com/android/internal/widget/remotecompose/core/operations/IntegerExpression.java
index c9a8508..6375f00 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/IntegerExpression.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/IntegerExpression.java
@@ -18,6 +18,8 @@
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT;
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT_ARRAY;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.RemoteContext;
@@ -45,7 +47,7 @@
public int[] mPreCalcValue;
private float mLastChange = Float.NaN;
public static final int MAX_SIZE = 320;
- IntegerExpressionEvaluator mExp = new IntegerExpressionEvaluator();
+ @NonNull IntegerExpressionEvaluator mExp = new IntegerExpressionEvaluator();
public IntegerExpression(int id, int mask, int[] value) {
this.mId = id;
@@ -54,7 +56,7 @@
}
@Override
- public void updateVariables(RemoteContext context) {
+ public void updateVariables(@NonNull RemoteContext context) {
if (mPreCalcValue == null || mPreCalcValue.length != mSrcValue.length) {
mPreCalcValue = new int[mSrcValue.length];
}
@@ -70,7 +72,7 @@
}
@Override
- public void registerListening(RemoteContext context) {
+ public void registerListening(@NonNull RemoteContext context) {
for (int i = 0; i < mSrcValue.length; i++) {
if (isId(mMask, i, mSrcValue[i])) {
context.listensTo(mSrcValue[i], this);
@@ -79,7 +81,7 @@
}
@Override
- public void apply(RemoteContext context) {
+ public void apply(@NonNull RemoteContext context) {
updateVariables(context);
float t = context.getAnimationTime();
if (Float.isNaN(mLastChange)) {
@@ -95,7 +97,7 @@
* @param context current context
* @return the resulting value
*/
- public int evaluate(RemoteContext context) {
+ public int evaluate(@NonNull RemoteContext context) {
updateVariables(context);
float t = context.getAnimationTime();
if (Float.isNaN(mLastChange)) {
@@ -105,10 +107,11 @@
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(buffer, mId, mMask, mSrcValue);
}
+ @NonNull
@Override
public String toString() {
StringBuilder s = new StringBuilder();
@@ -132,6 +135,7 @@
return "IntegerExpression[" + mId + "] = (" + s + ")";
}
+ @NonNull
public static String name() {
return CLASS_NAME;
}
@@ -148,7 +152,7 @@
* @param mask the mask bits of ints & operators or variables
* @param value array of integers to be evaluated
*/
- public static void apply(WireBuffer buffer, int id, int mask, int[] value) {
+ public static void apply(@NonNull WireBuffer buffer, int id, int mask, @NonNull int[] value) {
buffer.start(OP_CODE);
buffer.writeInt(id);
buffer.writeInt(mask);
@@ -158,7 +162,7 @@
}
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int id = buffer.readInt();
int mask = buffer.readInt();
int len = buffer.readInt();
@@ -173,7 +177,7 @@
operations.add(new IntegerExpression(id, mask, values));
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Data Operations", OP_CODE, CLASS_NAME)
.description("Expression that computes an integer")
.field(DocumentedOperation.INT, "id", "id of integer")
@@ -182,6 +186,7 @@
.field(INT_ARRAY, "values", "length", "Array of ints");
}
+ @NonNull
@Override
public String deepToString(String indent) {
return indent + toString();
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixRestore.java b/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixRestore.java
index 04f8a50..6a620e5 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixRestore.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixRestore.java
@@ -15,6 +15,8 @@
*/
package com.android.internal.widget.remotecompose.core.operations;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.PaintContext;
@@ -31,20 +33,22 @@
public MatrixRestore() {}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(buffer);
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(WireBuffer buffer, @NonNull List<Operation> operations) {
MatrixRestore op = new MatrixRestore();
operations.add(op);
}
+ @NonNull
@Override
public String toString() {
return "MatrixRestore";
}
+ @NonNull
public static String name() {
return CLASS_NAME;
}
@@ -53,17 +57,17 @@
return OP_CODE;
}
- public static void apply(WireBuffer buffer) {
+ public static void apply(@NonNull WireBuffer buffer) {
buffer.start(OP_CODE);
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Canvas Operations", OP_CODE, CLASS_NAME)
.description("Restore the matrix and clip");
}
@Override
- public void paint(PaintContext context) {
+ public void paint(@NonNull PaintContext context) {
context.matrixRestore();
}
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixRotate.java b/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixRotate.java
index df10f32..438a2aa 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixRotate.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixRotate.java
@@ -15,6 +15,8 @@
*/
package com.android.internal.widget.remotecompose.core.operations;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.PaintContext;
@@ -28,9 +30,10 @@
public static final int OP_CODE = Operations.MATRIX_ROTATE;
private static final String CLASS_NAME = "MatrixRotate";
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
Maker m =
new Maker() {
+ @NonNull
@Override
public DrawBase3 create(float v1, float v2, float v3) {
return new MatrixRotate(v1, v2, v3);
@@ -43,11 +46,12 @@
return OP_CODE;
}
+ @NonNull
public static String name() {
return CLASS_NAME;
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Canvas Operations", OP_CODE, CLASS_NAME)
.description("apply rotation to matrix")
.field(DocumentedOperation.FLOAT, "rotate", "Angle to rotate")
@@ -56,7 +60,7 @@
}
@Override
- protected void write(WireBuffer buffer, float v1, float v2, float v3) {
+ protected void write(@NonNull WireBuffer buffer, float v1, float v2, float v3) {
apply(buffer, v1, v2, v3);
}
@@ -66,7 +70,7 @@
}
@Override
- public void paint(PaintContext context) {
+ public void paint(@NonNull PaintContext context) {
context.matrixRotate(mV1, mV2, mV3);
}
@@ -78,7 +82,7 @@
* @param y1 X Pivot point
* @param x2 Y Pivot point
*/
- public static void apply(WireBuffer buffer, float x1, float y1, float x2) {
+ public static void apply(@NonNull WireBuffer buffer, float x1, float y1, float x2) {
buffer.start(OP_CODE);
buffer.writeFloat(x1);
buffer.writeFloat(y1);
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixSave.java b/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixSave.java
index 67612c7..1880b19 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixSave.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixSave.java
@@ -15,6 +15,8 @@
*/
package com.android.internal.widget.remotecompose.core.operations;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.PaintContext;
@@ -29,20 +31,22 @@
private static final String CLASS_NAME = "MatrixSave";
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(buffer);
}
+ @NonNull
@Override
public String toString() {
return "MatrixSave;";
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(WireBuffer buffer, @NonNull List<Operation> operations) {
MatrixSave op = new MatrixSave();
operations.add(op);
}
+ @NonNull
public static String name() {
return CLASS_NAME;
}
@@ -51,17 +55,17 @@
return OP_CODE;
}
- public static void apply(WireBuffer buffer) {
+ public static void apply(@NonNull WireBuffer buffer) {
buffer.start(Operations.MATRIX_SAVE);
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Canvas Operations", OP_CODE, CLASS_NAME)
.description("Save the matrix and clip to a stack");
}
@Override
- public void paint(PaintContext context) {
+ public void paint(@NonNull PaintContext context) {
context.matrixSave();
}
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixScale.java b/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixScale.java
index 26c898a..6304584 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixScale.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixScale.java
@@ -15,6 +15,8 @@
*/
package com.android.internal.widget.remotecompose.core.operations;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.PaintContext;
@@ -28,7 +30,7 @@
public static final int OP_CODE = Operations.MATRIX_SCALE;
public static final String CLASS_NAME = "MatrixScale";
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
Maker m = MatrixScale::new;
read(m, buffer, operations);
}
@@ -37,16 +39,17 @@
return OP_CODE;
}
+ @NonNull
public static String name() {
return CLASS_NAME;
}
@Override
- protected void write(WireBuffer buffer, float v1, float v2, float v3, float v4) {
+ protected void write(@NonNull WireBuffer buffer, float v1, float v2, float v3, float v4) {
apply(buffer, v1, v2, v3, v4);
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Canvas Operations", OP_CODE, CLASS_NAME)
.description("Draw the specified Oval")
.field(DocumentedOperation.FLOAT, "scaleX", "The amount to scale in X")
@@ -61,7 +64,7 @@
}
@Override
- public void paint(PaintContext context) {
+ public void paint(@NonNull PaintContext context) {
context.matrixScale(mX1, mY1, mX2, mY2);
}
@@ -74,7 +77,7 @@
* @param x2 end x of the DrawOval
* @param y2 end y of the DrawOval
*/
- public static void apply(WireBuffer buffer, float x1, float y1, float x2, float y2) {
+ public static void apply(@NonNull WireBuffer buffer, float x1, float y1, float x2, float y2) {
write(buffer, OP_CODE, x1, y1, x2, y2);
}
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixSkew.java b/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixSkew.java
index d641178..675cf0d 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixSkew.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixSkew.java
@@ -17,6 +17,8 @@
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.FLOAT;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.PaintContext;
@@ -29,7 +31,7 @@
public static final int OP_CODE = Operations.MATRIX_SKEW;
public static final String CLASS_NAME = "MatrixSkew";
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
Maker m = MatrixSkew::new;
read(m, buffer, operations);
}
@@ -38,16 +40,17 @@
return OP_CODE;
}
+ @NonNull
public static String name() {
return CLASS_NAME;
}
@Override
- protected void write(WireBuffer buffer, float v1, float v2) {
+ protected void write(@NonNull WireBuffer buffer, float v1, float v2) {
apply(buffer, v1, v2);
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Canvas Operations", OP_CODE, CLASS_NAME)
.description("Current matrix with the specified skew.")
.field(FLOAT, "skewX", "The amount to skew in X")
@@ -60,7 +63,7 @@
}
@Override
- public void paint(PaintContext context) {
+ public void paint(@NonNull PaintContext context) {
context.matrixSkew(mV1, mV2);
}
@@ -71,7 +74,7 @@
* @param x1 start x of DrawOval
* @param y1 start y of the DrawOval
*/
- public static void apply(WireBuffer buffer, float x1, float y1) {
+ public static void apply(@NonNull WireBuffer buffer, float x1, float y1) {
write(buffer, OP_CODE, x1, y1);
}
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixTranslate.java b/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixTranslate.java
index e008292..b0a7d35 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixTranslate.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixTranslate.java
@@ -15,6 +15,8 @@
*/
package com.android.internal.widget.remotecompose.core.operations;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.PaintContext;
@@ -28,7 +30,7 @@
public static final int OP_CODE = Operations.MATRIX_TRANSLATE;
public static final String CLASS_NAME = "MatrixTranslate";
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
Maker m = MatrixTranslate::new;
read(m, buffer, operations);
}
@@ -37,16 +39,17 @@
return OP_CODE;
}
+ @NonNull
public static String name() {
return CLASS_NAME;
}
@Override
- protected void write(WireBuffer buffer, float v1, float v2) {
+ protected void write(@NonNull WireBuffer buffer, float v1, float v2) {
apply(buffer, v1, v2);
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Canvas Operations", OP_CODE, "MatrixTranslate")
.description("Preconcat the current matrix with the specified translation")
.field(DocumentedOperation.FLOAT, "dx", "The distance to translate in X")
@@ -59,7 +62,7 @@
}
@Override
- public void paint(PaintContext context) {
+ public void paint(@NonNull PaintContext context) {
context.matrixTranslate(mV1, mV2);
}
@@ -70,7 +73,7 @@
* @param x1 start x of DrawOval
* @param y1 start y of the DrawOval
*/
- public static void apply(WireBuffer buffer, float x1, float y1) {
+ public static void apply(@NonNull WireBuffer buffer, float x1, float y1) {
write(buffer, OP_CODE, x1, y1);
}
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/NamedVariable.java b/core/java/com/android/internal/widget/remotecompose/core/operations/NamedVariable.java
index fa6e271..6310521e 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/NamedVariable.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/NamedVariable.java
@@ -18,6 +18,8 @@
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT;
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.UTF8;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.RemoteContext;
@@ -47,10 +49,11 @@
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(buffer, mVarId, mVarType, mVarName);
}
+ @NonNull
@Override
public String toString() {
return "VariableName["
@@ -61,6 +64,7 @@
+ mVarType;
}
+ @NonNull
public static String name() {
return CLASS_NAME;
}
@@ -77,21 +81,22 @@
* @param varType The type of variable
* @param text String
*/
- public static void apply(WireBuffer buffer, int varId, int varType, String text) {
+ public static void apply(
+ @NonNull WireBuffer buffer, int varId, int varType, @NonNull String text) {
buffer.start(Operations.NAMED_VARIABLE);
buffer.writeInt(varId);
buffer.writeInt(varType);
buffer.writeUTF8(text);
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int varId = buffer.readInt();
int varType = buffer.readInt();
String text = buffer.readUTF8(MAX_STRING_SIZE);
operations.add(new NamedVariable(varId, varType, text));
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Data Operations", OP_CODE, CLASS_NAME)
.description("Add a string name for an ID")
.field(DocumentedOperation.INT, "varId", "id to label")
@@ -100,10 +105,11 @@
}
@Override
- public void apply(RemoteContext context) {
+ public void apply(@NonNull RemoteContext context) {
context.loadVariableName(mVarName, mVarId, mVarType);
}
+ @NonNull
@Override
public String deepToString(String indent) {
return indent + toString();
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/PaintData.java b/core/java/com/android/internal/widget/remotecompose/core/operations/PaintData.java
index 095a010..527d5610 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/PaintData.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/PaintData.java
@@ -18,6 +18,8 @@
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT;
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT_ARRAY;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.PaintContext;
@@ -33,31 +35,33 @@
public class PaintData extends PaintOperation implements VariableSupport {
private static final int OP_CODE = Operations.PAINT_VALUES;
private static final String CLASS_NAME = "PaintData";
- public PaintBundle mPaintData = new PaintBundle();
+ @NonNull public PaintBundle mPaintData = new PaintBundle();
public static final int MAX_STRING_SIZE = 4000;
public PaintData() {}
@Override
- public void updateVariables(RemoteContext context) {
+ public void updateVariables(@NonNull RemoteContext context) {
mPaintData.updateVariables(context);
}
@Override
- public void registerListening(RemoteContext context) {
+ public void registerListening(@NonNull RemoteContext context) {
mPaintData.registerVars(context, this);
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(buffer, mPaintData);
}
+ @NonNull
@Override
public String toString() {
return "PaintData " + "\"" + mPaintData + "\"";
}
+ @NonNull
public static String name() {
return CLASS_NAME;
}
@@ -66,31 +70,32 @@
return OP_CODE;
}
- public static void apply(WireBuffer buffer, PaintBundle paintBundle) {
+ public static void apply(@NonNull WireBuffer buffer, @NonNull PaintBundle paintBundle) {
buffer.start(Operations.PAINT_VALUES);
paintBundle.writeBundle(buffer);
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
PaintData data = new PaintData();
data.mPaintData.readBundle(buffer);
operations.add(data);
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Data Operations", OP_CODE, CLASS_NAME)
.description("Encode a Paint ")
.field(INT, "length", "id string")
.field(INT_ARRAY, "paint", "length", "path encoded as floats");
}
+ @NonNull
@Override
public String deepToString(String indent) {
return indent + toString();
}
@Override
- public void paint(PaintContext context) {
+ public void paint(@NonNull PaintContext context) {
context.applyPaint(mPaintData);
}
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/PathData.java b/core/java/com/android/internal/widget/remotecompose/core/operations/PathData.java
index 13d5a49..06a1fec 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/PathData.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/PathData.java
@@ -18,6 +18,9 @@
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.FLOAT_ARRAY;
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.RemoteContext;
@@ -43,7 +46,7 @@
}
@Override
- public void updateVariables(RemoteContext context) {
+ public void updateVariables(@NonNull RemoteContext context) {
for (int i = 0; i < mFloatPath.length; i++) {
float v = mFloatPath[i];
if (Utils.isVariable(v)) {
@@ -55,7 +58,7 @@
}
@Override
- public void registerListening(RemoteContext context) {
+ public void registerListening(@NonNull RemoteContext context) {
for (float v : mFloatPath) {
if (Float.isNaN(v)) {
context.listensTo(Utils.idFromNan(v), this);
@@ -64,15 +67,17 @@
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(buffer, mInstanceId, mOutputPath);
}
+ @NonNull
@Override
public String deepToString(String indent) {
return pathString(mFloatPath);
}
+ @NonNull
@Override
public String toString() {
return "PathData[" + mInstanceId + "] = " + "\"" + deepToString(" ") + "\"";
@@ -102,6 +107,7 @@
public static final float CLOSE_NAN = Utils.asNan(CLOSE);
public static final float DONE_NAN = Utils.asNan(DONE);
+ @NonNull
public static String name() {
return CLASS_NAME;
}
@@ -110,7 +116,7 @@
return OP_CODE;
}
- public static void apply(WireBuffer buffer, int id, float[] data) {
+ public static void apply(@NonNull WireBuffer buffer, int id, @NonNull float[] data) {
buffer.start(Operations.DATA_PATH);
buffer.writeInt(id);
buffer.writeInt(data.length);
@@ -119,7 +125,7 @@
}
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int imageId = buffer.readInt();
int len = buffer.readInt();
float[] data = new float[len];
@@ -129,7 +135,7 @@
operations.add(new PathData(imageId, data));
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Data Operations", OP_CODE, CLASS_NAME)
.description("Encode a Path ")
.field(DocumentedOperation.INT, "id", "id string")
@@ -137,7 +143,8 @@
.field(FLOAT_ARRAY, "pathData", "length", "path encoded as floats");
}
- public static String pathString(float[] path) {
+ @NonNull
+ public static String pathString(@Nullable float[] path) {
if (path == null) {
return "null";
}
@@ -186,7 +193,7 @@
}
@Override
- public void apply(RemoteContext context) {
+ public void apply(@NonNull RemoteContext context) {
context.loadPathData(mInstanceId, mOutputPath);
}
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/RootContentBehavior.java b/core/java/com/android/internal/widget/remotecompose/core/operations/RootContentBehavior.java
index 4a8f532..6ff9ad7 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/RootContentBehavior.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/RootContentBehavior.java
@@ -15,6 +15,8 @@
*/
package com.android.internal.widget.remotecompose.core.operations;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.RemoteComposeOperation;
@@ -172,10 +174,11 @@
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(buffer, mScroll, mAlignment, mSizing, mMode);
}
+ @NonNull
@Override
public String toString() {
return "ROOT_CONTENT_BEHAVIOR scroll: "
@@ -187,15 +190,17 @@
}
@Override
- public void apply(RemoteContext context) {
+ public void apply(@NonNull RemoteContext context) {
context.setRootContentBehavior(mScroll, mAlignment, mSizing, mMode);
}
+ @NonNull
@Override
public String deepToString(String indent) {
return toString();
}
+ @NonNull
public static String name() {
return CLASS_NAME;
}
@@ -204,7 +209,8 @@
return OP_CODE;
}
- public static void apply(WireBuffer buffer, int scroll, int alignment, int sizing, int mode) {
+ public static void apply(
+ @NonNull WireBuffer buffer, int scroll, int alignment, int sizing, int mode) {
buffer.start(OP_CODE);
buffer.writeInt(scroll);
buffer.writeInt(alignment);
@@ -212,7 +218,7 @@
buffer.writeInt(mode);
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int scroll = buffer.readInt();
int alignment = buffer.readInt();
int sizing = buffer.readInt();
@@ -222,7 +228,7 @@
operations.add(rootContentBehavior);
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Protocol Operations", OP_CODE, CLASS_NAME)
.description("Describes the behaviour of the root")
.field(DocumentedOperation.INT, "scroll", "scroll")
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/RootContentDescription.java b/core/java/com/android/internal/widget/remotecompose/core/operations/RootContentDescription.java
index bff9029..c2d62a7 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/RootContentDescription.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/RootContentDescription.java
@@ -15,6 +15,8 @@
*/
package com.android.internal.widget.remotecompose.core.operations;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.RemoteComposeOperation;
@@ -41,25 +43,28 @@
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(buffer, mContentDescription);
}
+ @NonNull
@Override
public String toString() {
return "RootContentDescription " + mContentDescription;
}
@Override
- public void apply(RemoteContext context) {
+ public void apply(@NonNull RemoteContext context) {
context.setDocumentContentDescription(mContentDescription);
}
+ @NonNull
@Override
public String deepToString(String indent) {
return toString();
}
+ @NonNull
public static String name() {
return CLASS_NAME;
}
@@ -68,18 +73,18 @@
return OP_CODE;
}
- public static void apply(WireBuffer buffer, int contentDescription) {
+ public static void apply(@NonNull WireBuffer buffer, int contentDescription) {
buffer.start(Operations.ROOT_CONTENT_DESCRIPTION);
buffer.writeInt(contentDescription);
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int contentDescription = buffer.readInt();
RootContentDescription header = new RootContentDescription(contentDescription);
operations.add(header);
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Protocol Operations", OP_CODE, CLASS_NAME)
.description("Content description of root")
.field(DocumentedOperation.INT, "id", "id of Int");
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/ShaderData.java b/core/java/com/android/internal/widget/remotecompose/core/operations/ShaderData.java
index 7ec7879..ae61c3a 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/ShaderData.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/ShaderData.java
@@ -22,6 +22,9 @@
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.SHORT;
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.UTF8;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.RemoteContext;
@@ -43,17 +46,17 @@
private static final String CLASS_NAME = "ShaderData";
int mShaderTextId; // the actual text of a shader
int mShaderID; // allows shaders to be referenced by number
- HashMap<String, float[]> mUniformRawFloatMap = null;
- HashMap<String, float[]> mUniformFloatMap = null;
- HashMap<String, int[]> mUniformIntMap = null;
- HashMap<String, Integer> mUniformBitmapMap = null;
+ @Nullable HashMap<String, float[]> mUniformRawFloatMap = null;
+ @Nullable HashMap<String, float[]> mUniformFloatMap = null;
+ @Nullable HashMap<String, int[]> mUniformIntMap = null;
+ @Nullable HashMap<String, Integer> mUniformBitmapMap = null;
public ShaderData(
int shaderID,
int shaderTextId,
- HashMap<String, float[]> floatMap,
- HashMap<String, int[]> intMap,
- HashMap<String, Integer> bitmapMap) {
+ @Nullable HashMap<String, float[]> floatMap,
+ @Nullable HashMap<String, int[]> intMap,
+ @Nullable HashMap<String, Integer> bitmapMap) {
mShaderID = shaderID;
mShaderTextId = shaderTextId;
if (floatMap != null) {
@@ -89,6 +92,7 @@
*
* @return Names of all uniform floats or empty array
*/
+ @NonNull
public String[] getUniformFloatNames() {
if (mUniformFloatMap == null) return new String[0];
return mUniformFloatMap.keySet().toArray(new String[0]);
@@ -109,6 +113,7 @@
*
* @return Name of all integer uniforms
*/
+ @NonNull
public String[] getUniformIntegerNames() {
if (mUniformIntMap == null) return new String[0];
return mUniformIntMap.keySet().toArray(new String[0]);
@@ -129,6 +134,7 @@
*
* @return Name of all bitmap uniforms
*/
+ @NonNull
public String[] getUniformBitmapNames() {
if (mUniformBitmapMap == null) return new String[0];
return mUniformBitmapMap.keySet().toArray(new String[0]);
@@ -145,7 +151,7 @@
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(
buffer,
mShaderID,
@@ -155,13 +161,14 @@
mUniformBitmapMap);
}
+ @NonNull
@Override
public String toString() {
return "SHADER DATA " + mShaderID;
}
@Override
- public void updateVariables(RemoteContext context) {
+ public void updateVariables(@NonNull RemoteContext context) {
for (String name : mUniformRawFloatMap.keySet()) {
float[] value = mUniformRawFloatMap.get(name);
float[] out = null;
@@ -178,7 +185,7 @@
}
@Override
- public void registerListening(RemoteContext context) {
+ public void registerListening(@NonNull RemoteContext context) {
for (String name : mUniformRawFloatMap.keySet()) {
float[] value = mUniformRawFloatMap.get(name);
for (float v : value) {
@@ -189,6 +196,7 @@
}
}
+ @NonNull
public static String name() {
return CLASS_NAME;
}
@@ -208,12 +216,12 @@
* @param bitmapMap the map of bitmap uniforms
*/
public static void apply(
- WireBuffer buffer,
+ @NonNull WireBuffer buffer,
int shaderID,
int shaderTextId,
- HashMap<String, float[]> floatMap,
- HashMap<String, int[]> intMap,
- HashMap<String, Integer> bitmapMap) {
+ @Nullable HashMap<String, float[]> floatMap,
+ @Nullable HashMap<String, int[]> intMap,
+ @Nullable HashMap<String, Integer> bitmapMap) {
buffer.start(OP_CODE);
buffer.writeInt(shaderID);
@@ -256,7 +264,7 @@
}
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int shaderID = buffer.readInt();
int shaderTextId = buffer.readInt();
HashMap<String, float[]> floatMap = null;
@@ -308,7 +316,7 @@
operations.add(new ShaderData(shaderID, shaderTextId, floatMap, intMap, bitmapMap));
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Data Operations", OP_CODE, CLASS_NAME)
.description("Shader")
.field(DocumentedOperation.INT, "shaderID", "id of shader")
@@ -326,10 +334,11 @@
}
@Override
- public void apply(RemoteContext context) {
+ public void apply(@NonNull RemoteContext context) {
context.loadShader(mShaderID, this);
}
+ @NonNull
@Override
public String deepToString(String indent) {
return indent + toString();
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/TextData.java b/core/java/com/android/internal/widget/remotecompose/core/operations/TextData.java
index 6383249..dbaef7e 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/TextData.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/TextData.java
@@ -17,6 +17,8 @@
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.UTF8;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.RemoteContext;
@@ -42,15 +44,17 @@
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(buffer, mTextId, mText);
}
+ @NonNull
@Override
public String toString() {
return "TextData[" + mTextId + "] = \"" + Utils.trimString(mText, 10) + "\"";
}
+ @NonNull
public static String name() {
return CLASS_NAME;
}
@@ -59,20 +63,20 @@
return OP_CODE;
}
- public static void apply(WireBuffer buffer, int textId, String text) {
+ public static void apply(@NonNull WireBuffer buffer, int textId, @NonNull String text) {
buffer.start(OP_CODE);
buffer.writeInt(textId);
buffer.writeUTF8(text);
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int textId = buffer.readInt();
String text = buffer.readUTF8(MAX_STRING_SIZE);
operations.add(new TextData(textId, text));
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Data Operations", OP_CODE, CLASS_NAME)
.description("Encode a string ")
.field(DocumentedOperation.INT, "id", "id string")
@@ -80,20 +84,22 @@
}
@Override
- public void apply(RemoteContext context) {
+ public void apply(@NonNull RemoteContext context) {
context.loadText(mTextId, mText);
}
+ @NonNull
@Override
public String deepToString(String indent) {
return indent + toString();
}
@Override
- public void serializeToString(int indent, StringSerializer serializer) {
+ public void serializeToString(int indent, @NonNull StringSerializer serializer) {
serializer.append(indent, getSerializedName() + "<" + mTextId + "> = \"" + mText + "\"");
}
+ @NonNull
private String getSerializedName() {
return "DATA_TEXT";
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/TextFromFloat.java b/core/java/com/android/internal/widget/remotecompose/core/operations/TextFromFloat.java
index 0d966d1..fb5087f 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/TextFromFloat.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/TextFromFloat.java
@@ -18,6 +18,8 @@
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT;
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.SHORT;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.RemoteContext;
@@ -87,10 +89,11 @@
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(buffer, mTextId, mValue, mDigitsBefore, mDigitsAfter, mFlags);
}
+ @NonNull
@Override
public String toString() {
return "TextFromFloat["
@@ -106,19 +109,20 @@
}
@Override
- public void updateVariables(RemoteContext context) {
+ public void updateVariables(@NonNull RemoteContext context) {
if (Float.isNaN(mValue)) {
mOutValue = context.getFloat(Utils.idFromNan(mValue));
}
}
@Override
- public void registerListening(RemoteContext context) {
+ public void registerListening(@NonNull RemoteContext context) {
if (Float.isNaN(mValue)) {
context.listensTo(Utils.idFromNan(mValue), this);
}
}
+ @NonNull
public static String name() {
return CLASS_NAME;
}
@@ -138,7 +142,7 @@
* @param flags flags that control if and how to fill the empty spots
*/
public static void apply(
- WireBuffer buffer,
+ @NonNull WireBuffer buffer,
int textId,
float value,
short digitsBefore,
@@ -151,7 +155,7 @@
buffer.writeInt(flags);
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int textId = buffer.readInt();
float value = buffer.readFloat();
int tmp = buffer.readInt();
@@ -162,7 +166,7 @@
operations.add(new TextFromFloat(textId, value, pre, post, flags));
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Expressions Operations", OP_CODE, CLASS_NAME)
.description("Draw text along path object")
.field(DocumentedOperation.INT, "textId", "id of the text generated")
@@ -173,12 +177,13 @@
}
@Override
- public void apply(RemoteContext context) {
+ public void apply(@NonNull RemoteContext context) {
float v = mOutValue;
String s = StringUtils.floatToString(v, mDigitsBefore, mDigitsAfter, mPre, mAfter);
context.loadText(mTextId, s);
}
+ @NonNull
@Override
public String deepToString(String indent) {
return indent + toString();
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/TextLookup.java b/core/java/com/android/internal/widget/remotecompose/core/operations/TextLookup.java
index b04d698..2129edd 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/TextLookup.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/TextLookup.java
@@ -18,6 +18,8 @@
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.FLOAT;
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.RemoteContext;
@@ -48,10 +50,11 @@
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(buffer, mTextId, mDataSetId, mIndex);
}
+ @NonNull
@Override
public String toString() {
return "TextLookup["
@@ -63,19 +66,20 @@
}
@Override
- public void updateVariables(RemoteContext context) {
+ public void updateVariables(@NonNull RemoteContext context) {
if (Float.isNaN(mIndex)) {
mOutIndex = context.getFloat(Utils.idFromNan(mIndex));
}
}
@Override
- public void registerListening(RemoteContext context) {
+ public void registerListening(@NonNull RemoteContext context) {
if (Float.isNaN(mIndex)) {
context.listensTo(Utils.idFromNan(mIndex), this);
}
}
+ @NonNull
public static String name() {
return CLASS_NAME;
}
@@ -92,21 +96,21 @@
* @param dataSet float pointer to the array/list to turn int a string
* @param index index of element to return
*/
- public static void apply(WireBuffer buffer, int textId, int dataSet, float index) {
+ public static void apply(@NonNull WireBuffer buffer, int textId, int dataSet, float index) {
buffer.start(OP_CODE);
buffer.writeInt(textId);
buffer.writeInt(dataSet);
buffer.writeFloat(index);
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int textId = buffer.readInt();
int dataSetId = buffer.readInt();
float index = buffer.readFloat();
operations.add(new TextLookup(textId, dataSetId, index));
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Expressions Operations", OP_CODE, CLASS_NAME)
.description("Look an array and turn into a text object")
.field(INT, "textId", "id of the text generated")
@@ -115,11 +119,12 @@
}
@Override
- public void apply(RemoteContext context) {
+ public void apply(@NonNull RemoteContext context) {
int id = context.getCollectionsAccess().getId(mDataSetId, (int) mOutIndex);
context.loadText(mTextId, context.getText(id));
}
+ @NonNull
@Override
public String deepToString(String indent) {
return indent + toString();
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/TextLookupInt.java b/core/java/com/android/internal/widget/remotecompose/core/operations/TextLookupInt.java
index 171bea2..ea550cb 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/TextLookupInt.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/TextLookupInt.java
@@ -17,6 +17,8 @@
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.RemoteContext;
@@ -45,10 +47,11 @@
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(buffer, mTextId, mDataSetId, mIndex);
}
+ @NonNull
@Override
public String toString() {
return "TextLookupInt["
@@ -60,15 +63,16 @@
}
@Override
- public void updateVariables(RemoteContext context) {
+ public void updateVariables(@NonNull RemoteContext context) {
mOutIndex = context.getInteger(mIndex);
}
@Override
- public void registerListening(RemoteContext context) {
+ public void registerListening(@NonNull RemoteContext context) {
context.listensTo(mIndex, this);
}
+ @NonNull
public static String name() {
return CLASS_NAME;
}
@@ -85,21 +89,21 @@
* @param dataSet float pointer to the array/list to turn int a string
* @param indexId index of element to return
*/
- public static void apply(WireBuffer buffer, int textId, int dataSet, int indexId) {
+ public static void apply(@NonNull WireBuffer buffer, int textId, int dataSet, int indexId) {
buffer.start(OP_CODE);
buffer.writeInt(textId);
buffer.writeInt(dataSet);
buffer.writeInt(indexId);
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int textId = buffer.readInt();
int dataSetId = buffer.readInt();
int indexId = buffer.readInt();
operations.add(new TextLookupInt(textId, dataSetId, indexId));
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Expressions Operations", OP_CODE, CLASS_NAME)
.description("Look up an array and turn into a text object")
.field(DocumentedOperation.INT, "textId", "id of the text generated")
@@ -108,11 +112,12 @@
}
@Override
- public void apply(RemoteContext context) {
+ public void apply(@NonNull RemoteContext context) {
int id = context.getCollectionsAccess().getId(mDataSetId, (int) mOutIndex);
context.loadText(mTextId, context.getText(id));
}
+ @NonNull
@Override
public String deepToString(String indent) {
return indent + toString();
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/TextMerge.java b/core/java/com/android/internal/widget/remotecompose/core/operations/TextMerge.java
index 78cc674..fa18b4d 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/TextMerge.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/TextMerge.java
@@ -17,6 +17,8 @@
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.RemoteContext;
@@ -41,15 +43,17 @@
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(buffer, mTextId, mSrcId1, mSrcId2);
}
+ @NonNull
@Override
public String toString() {
return "TextMerge[" + mTextId + "] = [" + mSrcId1 + " ] + [ " + mSrcId2 + "]";
}
+ @NonNull
public static String name() {
return CLASS_NAME;
}
@@ -66,14 +70,14 @@
* @param srcId1 source text 1
* @param srcId2 source text 2
*/
- public static void apply(WireBuffer buffer, int textId, int srcId1, int srcId2) {
+ public static void apply(@NonNull WireBuffer buffer, int textId, int srcId1, int srcId2) {
buffer.start(OP_CODE);
buffer.writeInt(textId);
buffer.writeInt(srcId1);
buffer.writeInt(srcId2);
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int textId = buffer.readInt();
int srcId1 = buffer.readInt();
int srcId2 = buffer.readInt();
@@ -81,7 +85,7 @@
operations.add(new TextMerge(textId, srcId1, srcId2));
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Data Operations", OP_CODE, CLASS_NAME)
.description("Merge two string into one")
.field(DocumentedOperation.INT, "textId", "id of the text")
@@ -90,12 +94,13 @@
}
@Override
- public void apply(RemoteContext context) {
+ public void apply(@NonNull RemoteContext context) {
String str1 = context.getText(mSrcId1);
String str2 = context.getText(mSrcId2);
context.loadText(mTextId, str1 + str2);
}
+ @NonNull
@Override
public String deepToString(String indent) {
return indent + toString();
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/Theme.java b/core/java/com/android/internal/widget/remotecompose/core/operations/Theme.java
index 845f25d..1e90ab1 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/Theme.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/Theme.java
@@ -17,6 +17,8 @@
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.RemoteComposeOperation;
@@ -49,25 +51,28 @@
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(buffer, mTheme);
}
+ @NonNull
@Override
public String toString() {
return "SET_THEME " + mTheme;
}
@Override
- public void apply(RemoteContext context) {
+ public void apply(@NonNull RemoteContext context) {
context.setTheme(mTheme);
}
+ @NonNull
@Override
public String deepToString(String indent) {
return indent + toString();
}
+ @NonNull
public static String name() {
return CLASS_NAME;
}
@@ -76,17 +81,17 @@
return OP_CODE;
}
- public static void apply(WireBuffer buffer, int theme) {
+ public static void apply(@NonNull WireBuffer buffer, int theme) {
buffer.start(OP_CODE);
buffer.writeInt(theme);
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int theme = buffer.readInt();
operations.add(new Theme(theme));
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Protocol Operations", OP_CODE, CLASS_NAME)
.description("Set a theme")
.field(INT, "THEME", "theme id")
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/TouchExpression.java b/core/java/com/android/internal/widget/remotecompose/core/operations/TouchExpression.java
new file mode 100644
index 0000000..b25a7f6
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/TouchExpression.java
@@ -0,0 +1,599 @@
+/*
+ * Copyright (C) 2023 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.internal.widget.remotecompose.core.operations;
+
+import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.FLOAT;
+import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.FLOAT_ARRAY;
+import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT;
+import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.SHORT;
+
+import com.android.internal.widget.remotecompose.core.Operation;
+import com.android.internal.widget.remotecompose.core.Operations;
+import com.android.internal.widget.remotecompose.core.RemoteContext;
+import com.android.internal.widget.remotecompose.core.TouchListener;
+import com.android.internal.widget.remotecompose.core.VariableSupport;
+import com.android.internal.widget.remotecompose.core.WireBuffer;
+import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder;
+import com.android.internal.widget.remotecompose.core.operations.layout.Component;
+import com.android.internal.widget.remotecompose.core.operations.utilities.AnimatedFloatExpression;
+import com.android.internal.widget.remotecompose.core.operations.utilities.NanMap;
+import com.android.internal.widget.remotecompose.core.operations.utilities.touch.VelocityEasing;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Operation to deal with Touch handling (typically on canvas) This support handling of many typical
+ * touch behaviours. Including animating to Notched, positions. and tweaking the dynamics of the
+ * animation.
+ */
+public class TouchExpression implements Operation, VariableSupport, TouchListener {
+ private static final int OP_CODE = Operations.TOUCH_EXPRESSION;
+ private static final String CLASS_NAME = "TouchExpression";
+ private float mDefValue;
+ private float mOutDefValue;
+ public int mId;
+ public float[] mSrcExp;
+ int mMode = 1; // 0 = delta, 1 = absolute
+ float mMax = 1;
+ float mMin = 1;
+ float mOutMax = 1;
+ float mOutMin = 1;
+ float mValue = 0;
+ boolean mUnmodified = true;
+ public float[] mPreCalcValue;
+ private float mLastChange = Float.NaN;
+ private float mLastCalculatedValue = Float.NaN;
+ AnimatedFloatExpression mExp = new AnimatedFloatExpression();
+ public static final int MAX_EXPRESSION_SIZE = 32;
+ private VelocityEasing mEasyTouch = new VelocityEasing();
+ private boolean mEasingToStop = false;
+ private float mTouchUpTime = 0;
+ private float mCurrentValue = Float.NaN;
+ private boolean mTouchDown = false;
+ float mMaxTime = 1;
+ float mMaxAcceleration = 5;
+ float mMaxVelocity = 7;
+ int mStopMode = 0;
+ boolean mWrapMode = false;
+ float[] mNotches;
+ float[] mStopSpec;
+ int mTouchEffects;
+ float mVelocityId;
+
+ public static final int STOP_GENTLY = 0;
+ public static final int STOP_ENDS = 2;
+ public static final int STOP_INSTANTLY = 1;
+ public static final int STOP_NOTCHES_EVEN = 3;
+ public static final int STOP_NOTCHES_PERCENTS = 4;
+ public static final int STOP_NOTCHES_ABSOLUTE = 5;
+ public static final int STOP_ABSOLUTE_POS = 6;
+
+ public TouchExpression(
+ int id,
+ float[] exp,
+ float defValue,
+ float min,
+ float max,
+ int touchEffects,
+ float velocityId,
+ int stopMode,
+ float[] stopSpec,
+ float[] easingSpec) {
+ this.mId = id;
+ this.mSrcExp = exp;
+ mOutDefValue = mDefValue = defValue;
+ mMode = STOP_ABSOLUTE_POS == stopMode ? 1 : 0;
+ mOutMax = mMax = max;
+ mTouchEffects = touchEffects;
+ mVelocityId = velocityId;
+ if (Float.isNaN(min) && Utils.idFromNan(min) == 0) {
+ mWrapMode = true;
+ } else {
+ mOutMin = mMin = min;
+ }
+ mStopMode = stopMode;
+ mStopSpec = stopSpec;
+ if (easingSpec != null) {
+ Utils.log("easingSpec " + Arrays.toString(easingSpec));
+ if (easingSpec.length >= 4) {
+ if (Float.floatToRawIntBits(easingSpec[0]) == 0) {
+ Utils.log("easingSpec[2] " + easingSpec[2]);
+ mMaxTime = easingSpec[1];
+ mMaxAcceleration = easingSpec[2];
+ mMaxVelocity = easingSpec[3];
+ }
+ }
+ }
+ }
+
+ @Override
+ public void updateVariables(RemoteContext context) {
+
+ if (mPreCalcValue == null || mPreCalcValue.length != mSrcExp.length) {
+ mPreCalcValue = new float[mSrcExp.length];
+ }
+ if (Float.isNaN(mMax)) {
+ mOutMax = context.getFloat(Utils.idFromNan(mMax));
+ }
+ if (Float.isNaN(mMin)) {
+ mOutMin = context.getFloat(Utils.idFromNan(mMin));
+ }
+ if (Float.isNaN(mDefValue)) {
+ mOutDefValue = context.getFloat(Utils.idFromNan(mDefValue));
+ }
+
+ boolean value_changed = false;
+ for (int i = 0; i < mSrcExp.length; i++) {
+ float v = mSrcExp[i];
+ if (Float.isNaN(v)
+ && !AnimatedFloatExpression.isMathOperator(v)
+ && !NanMap.isDataVariable(v)) {
+ float newValue = context.getFloat(Utils.idFromNan(v));
+
+ mPreCalcValue[i] = newValue;
+
+ } else {
+ mPreCalcValue[i] = mSrcExp[i];
+ }
+ }
+ float v = mLastCalculatedValue;
+ if (value_changed) { // inputs changed check if output changed
+ v = mExp.eval(mPreCalcValue, mPreCalcValue.length);
+ if (v != mLastCalculatedValue) {
+ mLastChange = context.getAnimationTime();
+ mLastCalculatedValue = v;
+ } else {
+ value_changed = false;
+ }
+ }
+ }
+
+ @Override
+ public void registerListening(RemoteContext context) {
+ if (Float.isNaN(mMax)) {
+ context.listensTo(Utils.idFromNan(mMax), this);
+ }
+ if (Float.isNaN(mMin)) {
+ context.listensTo(Utils.idFromNan(mMin), this);
+ }
+ if (Float.isNaN(mDefValue)) {
+ context.listensTo(Utils.idFromNan(mDefValue), this);
+ }
+ context.addTouchListener(this);
+ for (float v : mSrcExp) {
+ if (Float.isNaN(v)
+ && !AnimatedFloatExpression.isMathOperator(v)
+ && !NanMap.isDataVariable(v)) {
+ context.listensTo(Utils.idFromNan(v), this);
+ }
+ }
+ }
+
+ private float wrap(float pos) {
+ if (!mWrapMode) {
+ return pos;
+ }
+ pos = pos % mOutMax;
+ if (pos < 0) {
+ pos += mOutMax;
+ }
+ return pos;
+ }
+
+ private float getStopPosition(float pos, float slope) {
+ float target = pos + slope / mMaxAcceleration;
+ if (mWrapMode) {
+ pos = wrap(pos);
+ target = pos += +slope / mMaxAcceleration;
+ } else {
+ target = Math.max(Math.min(target, mOutMax), mOutMin);
+ }
+ float[] positions = new float[mStopSpec.length];
+ float min = (mWrapMode) ? 0 : mOutMin;
+
+ switch (mStopMode) {
+ case STOP_ENDS:
+ return ((pos + slope) > (mOutMax + min) / 2) ? mOutMax : min;
+ case STOP_INSTANTLY:
+ return pos;
+ case STOP_NOTCHES_EVEN:
+ int evenSpacing = (int) mStopSpec[0];
+ float step = (mOutMax - min) / evenSpacing;
+
+ float notch = min + step * (int) (0.5f + (target - mOutMin) / step);
+
+ notch = Math.max(Math.min(notch, mOutMax), min);
+ return notch;
+ case STOP_NOTCHES_PERCENTS:
+ positions = new float[mStopSpec.length];
+ float minPos = min;
+ float minPosDist = Math.abs(mOutMin - target);
+ for (int i = 0; i < positions.length; i++) {
+ float p = mOutMin + mStopSpec[i] * (mOutMax - mOutMin);
+ float dist = Math.abs(p - target);
+ if (minPosDist > dist) {
+ minPosDist = dist;
+ minPos = p;
+ }
+ }
+ return minPos;
+ case STOP_NOTCHES_ABSOLUTE:
+ positions = mStopSpec;
+ minPos = mOutMin;
+ minPosDist = Math.abs(mOutMin - target);
+ for (int i = 0; i < positions.length; i++) {
+ float dist = Math.abs(positions[i] - target);
+ if (minPosDist > dist) {
+ minPosDist = dist;
+ minPos = positions[i];
+ }
+ }
+ return minPos;
+ case STOP_GENTLY:
+ default:
+ return target;
+ }
+ }
+
+ void haptic(RemoteContext context) {
+ int touch = ((mTouchEffects) & 0xFF);
+ if ((mTouchEffects & (1 << 15)) != 0) {
+ touch = context.getInteger(mTouchEffects & 0x7FFF);
+ }
+
+ context.hapticEffect(touch);
+ }
+
+ float mLastValue = 0;
+
+ void crossNotchCheck(RemoteContext context) {
+ float prev = mLastValue;
+ float next = mCurrentValue;
+ mLastValue = next;
+
+ // System.out.println(mStopMode + " " + prev + " -> " + next);
+ float min = (mWrapMode) ? 0 : mOutMin;
+ float max = mOutMax;
+
+ switch (mStopMode) {
+ case STOP_ENDS:
+ if (((min - prev) * (max - prev) < 0) ^ ((min - next) * (max - next)) < 0) {
+ haptic(context);
+ }
+ break;
+ case STOP_INSTANTLY:
+ haptic(context);
+ break;
+ case STOP_NOTCHES_EVEN:
+ int evenSpacing = (int) mStopSpec[0];
+ float step = (max - min) / evenSpacing;
+ if ((int) ((prev - min) / step) != (int) ((next - min) / step)) {
+ haptic(context);
+ }
+ break;
+ case STOP_NOTCHES_PERCENTS:
+ for (int i = 0; i < mStopSpec.length; i++) {
+ float p = mOutMin + mStopSpec[i] * (mOutMax - mOutMin);
+ if ((prev - p) * (next - p) < 0) {
+ haptic(context);
+ }
+ }
+ break;
+ case STOP_NOTCHES_ABSOLUTE:
+ for (int i = 0; i < mStopSpec.length; i++) {
+ float p = mStopSpec[i];
+ if ((prev - p) * (next - p) < 0) {
+ haptic(context);
+ }
+ }
+ break;
+ case STOP_GENTLY:
+ }
+ }
+
+ float mScrLeft, mScrRight, mScrTop, mScrBottom;
+
+ @Override
+ public void apply(RemoteContext context) {
+ Component comp = context.lastComponent;
+ if (comp != null) {
+ float x = comp.getX();
+ float y = comp.getY();
+ float w = comp.getWidth();
+ float h = comp.getHeight();
+ comp = comp.getParent();
+ while (comp != null) {
+ x += comp.getX();
+ y += comp.getY();
+ comp = comp.getParent();
+ }
+ mScrLeft = x;
+ mScrTop = y;
+ mScrRight = w + x;
+ mScrBottom = h + y;
+ }
+ updateVariables(context);
+ if (mUnmodified) {
+ mCurrentValue = mOutDefValue;
+
+ context.loadFloat(mId, wrap(mCurrentValue));
+ return;
+ }
+ if (mEasingToStop) {
+ float time = context.getAnimationTime() - mTouchUpTime;
+ float value = mEasyTouch.getPos(time);
+ mCurrentValue = value;
+ value = wrap(value);
+ context.loadFloat(mId, value);
+ if (mEasyTouch.getDuration() < time) {
+ mEasingToStop = false;
+ }
+ crossNotchCheck(context);
+ return;
+ }
+ if (mTouchDown) {
+ float value =
+ mExp.eval(context.getCollectionsAccess(), mPreCalcValue, mPreCalcValue.length);
+ if (mMode == 0) {
+ value = mValueAtDown + (value - mDownTouchValue);
+ }
+ if (mWrapMode) {
+ value = wrap(value);
+ } else {
+ value = Math.min(Math.max(value, mOutMin), mOutMax);
+ }
+ mCurrentValue = value;
+ }
+ crossNotchCheck(context);
+ context.loadFloat(mId, wrap(mCurrentValue));
+ }
+
+ float mValueAtDown; // The currently "displayed" value at down
+ float mDownTouchValue; // The calculated value at down
+
+ @Override
+ public void touchDown(RemoteContext context, float x, float y) {
+
+ if (!(x >= mScrLeft && x <= mScrRight && y >= mScrTop && y <= mScrBottom)) {
+ Utils.log("NOT IN WINDOW " + x + ", " + y + " " + mScrLeft + ", " + mScrTop);
+ return;
+ }
+ mTouchDown = true;
+ mUnmodified = false;
+ if (mMode == 0) {
+ mValueAtDown = context.getFloat(mId);
+ mDownTouchValue =
+ mExp.eval(context.getCollectionsAccess(), mPreCalcValue, mPreCalcValue.length);
+ }
+ }
+
+ @Override
+ public void touchUp(RemoteContext context, float x, float y, float dx, float dy) {
+ // calculate the slope (using small changes)
+ if (!mTouchDown) {
+ return;
+ }
+ mTouchDown = false;
+ float dt = 0.0001f;
+ if (mStopMode == STOP_INSTANTLY) {
+ return;
+ }
+ float v = mExp.eval(context.getCollectionsAccess(), mPreCalcValue, mPreCalcValue.length);
+ for (int i = 0; i < mSrcExp.length; i++) {
+ if (Float.isNaN(mSrcExp[i])) {
+ int id = Utils.idFromNan(mSrcExp[i]);
+ if (id == RemoteContext.ID_TOUCH_POS_X) {
+ mPreCalcValue[i] = x + dx * dt;
+ } else if (id == RemoteContext.ID_TOUCH_POS_Y) {
+ mPreCalcValue[i] = y + dy * dt;
+ }
+ }
+ }
+ float vdt = mExp.eval(context.getCollectionsAccess(), mPreCalcValue, mPreCalcValue.length);
+ float slope = (vdt - v) / dt; // the rate of change with respect to the dx,dy movement
+ float value = context.getFloat(mId);
+
+ mTouchUpTime = context.getAnimationTime();
+
+ float dest = getStopPosition(value, slope);
+ mEasyTouch.config(value, dest, slope, mMaxTime, mMaxAcceleration, mMaxVelocity, null);
+ mEasingToStop = true;
+ }
+
+ @Override
+ public void touchDrag(RemoteContext context, float x, float y) {
+ if (!mTouchDown) {
+ return;
+ }
+ apply(context);
+ context.getDocument().getRootLayoutComponent().needsRepaint();
+ }
+
+ @Override
+ public void write(WireBuffer buffer) {
+ apply(
+ buffer,
+ mId,
+ mValue,
+ mMin,
+ mMax,
+ mVelocityId,
+ mTouchEffects,
+ mSrcExp,
+ mStopMode,
+ mNotches,
+ null);
+ }
+
+ @Override
+ public String toString() {
+ String[] labels = new String[mSrcExp.length];
+ for (int i = 0; i < mSrcExp.length; i++) {
+ if (Float.isNaN(mSrcExp[i])) {
+ labels[i] = "[" + Utils.idStringFromNan(mSrcExp[i]) + "]";
+ }
+ }
+ if (mPreCalcValue == null) {
+ return CLASS_NAME
+ + "["
+ + mId
+ + "] = ("
+ + AnimatedFloatExpression.toString(mSrcExp, labels)
+ + ")";
+ }
+ return CLASS_NAME
+ + "["
+ + mId
+ + "] = ("
+ + AnimatedFloatExpression.toString(mPreCalcValue, labels)
+ + ")";
+ }
+
+ // ===================== static ======================
+
+ public static String name() {
+ return CLASS_NAME;
+ }
+
+ public static int id() {
+ return OP_CODE;
+ }
+
+ /**
+ * Writes out the operation to the buffer
+ *
+ * @param buffer The buffer to write to
+ * @param id the id of the resulting float
+ * @param value the float expression array
+ */
+ public static void apply(
+ WireBuffer buffer,
+ int id,
+ float value,
+ float min,
+ float max,
+ float velocityId,
+ int touchEffects,
+ float[] exp,
+ int touchMode,
+ float[] touchSpec,
+ float[] easingSpec) {
+ buffer.start(OP_CODE);
+ buffer.writeInt(id);
+ buffer.writeFloat(value);
+ buffer.writeFloat(min);
+ buffer.writeFloat(max);
+ buffer.writeFloat(velocityId);
+ buffer.writeInt(touchEffects);
+ buffer.writeInt(exp.length);
+ for (float v : exp) {
+ buffer.writeFloat(v);
+ }
+ int len = 0;
+ if (touchSpec != null) {
+ len = touchSpec.length;
+ }
+ buffer.writeInt((touchMode << 16) | len);
+ for (int i = 0; i < len; i++) {
+ buffer.writeFloat(touchSpec[i]);
+ }
+
+ if (easingSpec != null) {
+ len = easingSpec.length;
+ } else {
+ len = 0;
+ }
+ buffer.writeInt(len);
+ for (int i = 0; i < len; i++) {
+ buffer.writeFloat(easingSpec[i]);
+ }
+ }
+
+ public static void read(WireBuffer buffer, List<Operation> operations) {
+ int id = buffer.readInt();
+ float startValue = buffer.readFloat();
+ float min = buffer.readFloat();
+ float max = buffer.readFloat();
+ float velocityId = buffer.readFloat(); // TODO future support
+ int touchEffects = buffer.readInt();
+ int len = buffer.readInt();
+ int valueLen = len & 0xFFFF;
+ if (valueLen > MAX_EXPRESSION_SIZE) {
+ throw new RuntimeException("Float expression to long");
+ }
+ float[] exp = new float[valueLen];
+ for (int i = 0; i < exp.length; i++) {
+ exp[i] = buffer.readFloat();
+ }
+ int stopLogic = buffer.readInt();
+ int stopLen = stopLogic & 0xFFFF;
+ int stopMode = stopLogic >> 16;
+
+ Utils.log("stopMode " + stopMode + " stopLen " + stopLen);
+ float[] stopsData = new float[stopLen];
+ for (int i = 0; i < stopsData.length; i++) {
+ stopsData[i] = buffer.readFloat();
+ }
+ int easingLen = buffer.readInt();
+
+ float[] easingData = new float[easingLen];
+ for (int i = 0; i < easingData.length; i++) {
+ easingData[i] = buffer.readFloat();
+ }
+
+ operations.add(
+ new TouchExpression(
+ id,
+ exp,
+ startValue,
+ min,
+ max,
+ touchEffects,
+ velocityId,
+ stopMode,
+ stopsData,
+ easingData));
+ }
+
+ public static void documentation(DocumentationBuilder doc) {
+ doc.operation("Expressions Operations", OP_CODE, CLASS_NAME)
+ .description("A Float expression")
+ .field(INT, "id", "The id of the Color")
+ .field(SHORT, "expression_length", "expression length")
+ .field(SHORT, "animation_length", "animation description length")
+ .field(
+ FLOAT_ARRAY,
+ "expression",
+ "expression_length",
+ "Sequence of Floats representing and expression")
+ .field(
+ FLOAT_ARRAY,
+ "AnimationSpec",
+ "animation_length",
+ "Sequence of Floats representing animation curve")
+ .field(FLOAT, "duration", "> time in sec")
+ .field(INT, "bits", "> WRAP|INITALVALUE | TYPE ")
+ .field(FLOAT_ARRAY, "spec", "> [SPEC PARAMETERS] ")
+ .field(FLOAT, "initialValue", "> [Initial value] ")
+ .field(FLOAT, "wrapValue", "> [Wrap value] ");
+ }
+
+ @Override
+ public String deepToString(String indent) {
+ return indent + toString();
+ }
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/Utils.java b/core/java/com/android/internal/widget/remotecompose/core/operations/Utils.java
index 8ebb40c..03f7e05 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/Utils.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/Utils.java
@@ -15,6 +15,8 @@
*/
package com.android.internal.widget.remotecompose.core.operations;
+import android.annotation.NonNull;
+
/** Utilities to be used across all core operations */
public class Utils {
public static float asNan(int v) {
@@ -30,11 +32,13 @@
return v - 0x100000000L;
}
+ @NonNull
public static String idStringFromNan(float value) {
int b = Float.floatToRawIntBits(value) & 0x3FFFFF;
return idString(b);
}
+ @NonNull
public static String idString(int b) {
return (b > 0xFFFFF) ? "A_" + (b & 0xFFFFF) : "" + b;
}
@@ -50,7 +54,8 @@
* @param n
* @return
*/
- public static String trimString(String str, int n) {
+ @NonNull
+ public static String trimString(@NonNull String str, int n) {
if (str.length() > n) {
str = str.substring(0, n - 3) + "...";
}
@@ -145,6 +150,7 @@
* @param color
* @return
*/
+ @NonNull
public static String colorInt(int color) {
String str = "000000000000" + Integer.toHexString(color);
return "0x" + str.substring(str.length() - 8);
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/AnimatableValue.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/AnimatableValue.java
new file mode 100644
index 0000000..e789710
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/AnimatableValue.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2024 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.internal.widget.remotecompose.core.operations.layout;
+
+import com.android.internal.widget.remotecompose.core.PaintContext;
+import com.android.internal.widget.remotecompose.core.operations.Utils;
+import com.android.internal.widget.remotecompose.core.operations.utilities.easing.FloatAnimation;
+import com.android.internal.widget.remotecompose.core.operations.utilities.easing.GeneralEasing;
+
+public class AnimatableValue {
+ boolean mIsVariable = false;
+ int mId = 0;
+ float mValue = 0f;
+
+ boolean mAnimate = false;
+ long mAnimateTargetTime = 0;
+ float mAnimateDuration = 300f;
+ float mTargetRotationX;
+ float mStartRotationX;
+
+ int mMotionEasingType = GeneralEasing.CUBIC_STANDARD;
+ FloatAnimation mMotionEasing;
+
+ public AnimatableValue(float value) {
+ if (Utils.isVariable(value)) {
+ mId = Utils.idFromNan(value);
+ mIsVariable = true;
+ } else {
+ mValue = value;
+ }
+ }
+
+ public float getValue() {
+ return mValue;
+ }
+
+ public float evaluate(PaintContext context) {
+ if (!mIsVariable) {
+ return mValue;
+ }
+ float value = context.getContext().mRemoteComposeState.getFloat(mId);
+
+ if (value != mValue && !mAnimate) {
+ // animate
+ mStartRotationX = mValue;
+ mTargetRotationX = value;
+ mAnimate = true;
+ mAnimateTargetTime = System.currentTimeMillis();
+ mMotionEasing =
+ new FloatAnimation(
+ mMotionEasingType, mAnimateDuration / 1000f, null, 0f, Float.NaN);
+ mMotionEasing.setTargetValue(1f);
+ }
+ if (mAnimate) {
+ float elapsed = System.currentTimeMillis() - mAnimateTargetTime;
+ float p = mMotionEasing.get(elapsed / mAnimateDuration);
+ mValue = (1 - p) * mStartRotationX + p * mTargetRotationX;
+ if (p >= 1f) {
+ mAnimate = false;
+ }
+ } else {
+ mValue = mTargetRotationX;
+ }
+
+ return mValue;
+ }
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/CanvasContent.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/CanvasContent.java
index 9d80d3c..9886518 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/CanvasContent.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/CanvasContent.java
@@ -17,6 +17,8 @@
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.WireBuffer;
@@ -38,6 +40,7 @@
super(parent, componentId, animationId, x, y, width, height);
}
+ @NonNull
public static String name() {
return "CanvasContent";
}
@@ -46,29 +49,30 @@
return Operations.LAYOUT_CANVAS_CONTENT;
}
+ @NonNull
@Override
protected String getSerializedName() {
return "CANVAS_CONTENT";
}
- public static void apply(WireBuffer buffer, int componentId) {
+ public static void apply(@NonNull WireBuffer buffer, int componentId) {
buffer.start(Operations.LAYOUT_CANVAS_CONTENT);
buffer.writeInt(componentId);
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int componentId = buffer.readInt();
operations.add(new CanvasContent(componentId, 0, 0, 0, 0, null, -1));
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Layout Operations", id(), name())
.field(INT, "COMPONENT_ID", "unique id for this component")
.description("Container for canvas commands.");
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(buffer, mComponentId);
}
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ClickHandler.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ClickHandler.java
new file mode 100644
index 0000000..0ca72fa
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ClickHandler.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2024 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.internal.widget.remotecompose.core.operations.layout;
+
+import com.android.internal.widget.remotecompose.core.CoreDocument;
+import com.android.internal.widget.remotecompose.core.RemoteContext;
+
+/** Interface to represent operations that can handle click events */
+public interface ClickHandler {
+
+ /**
+ * callback for a click event
+ *
+ * @param context the current context
+ * @param document the current document
+ * @param component the component on which the click has been received
+ * @param x the x position of the click in document coordinates
+ * @param y the y position of the click in document coordinates
+ */
+ void onClick(
+ RemoteContext context, CoreDocument document, Component component, float x, float y);
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ClickModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ClickModifierOperation.java
index d5ff07d..b567538 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ClickModifierOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ClickModifierOperation.java
@@ -15,6 +15,9 @@
*/
package com.android.internal.widget.remotecompose.core.operations.layout;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
import com.android.internal.widget.remotecompose.core.CoreDocument;
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
@@ -37,7 +40,7 @@
/** Represents a click modifier + actions */
public class ClickModifierOperation extends PaintOperation
- implements ModifierOperation, DecoratorComponent {
+ implements ModifierOperation, DecoratorComponent, ClickHandler {
private static final int OP_CODE = Operations.MODIFIER_CLICK;
long mAnimateRippleStart = 0;
@@ -48,9 +51,9 @@
float mWidth = 0;
float mHeight = 0;
- public float[] locationInWindow = new float[2];
+ @NonNull public float[] locationInWindow = new float[2];
- PaintBundle mPaint = new PaintBundle();
+ @NonNull PaintBundle mPaint = new PaintBundle();
public void animateRipple(float x, float y) {
mAnimateRippleStart = System.currentTimeMillis();
@@ -58,17 +61,19 @@
mAnimateRippleY = y;
}
- public ArrayList<Operation> mList = new ArrayList<>();
+ @NonNull public ArrayList<Operation> mList = new ArrayList<>();
+ @NonNull
public ArrayList<Operation> getList() {
return mList;
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(buffer);
}
+ @NonNull
@Override
public String toString() {
return "ClickModifier";
@@ -83,13 +88,14 @@
}
}
+ @NonNull
@Override
- public String deepToString(String indent) {
+ public String deepToString(@Nullable String indent) {
return (indent != null ? indent : "") + toString();
}
@Override
- public void paint(PaintContext context) {
+ public void paint(@NonNull PaintContext context) {
if (mAnimateRippleStart == 0) {
return;
}
@@ -137,7 +143,7 @@
}
@Override
- public void serializeToString(int indent, StringSerializer serializer) {
+ public void serializeToString(int indent, @NonNull StringSerializer serializer) {
serializer.append(indent, "CLICK_MODIFIER");
for (Operation o : mList) {
if (o instanceof ActionOperation) {
@@ -148,7 +154,11 @@
@Override
public void onClick(
- RemoteContext context, CoreDocument document, Component component, float x, float y) {
+ RemoteContext context,
+ CoreDocument document,
+ @NonNull Component component,
+ float x,
+ float y) {
if (!component.isVisible()) {
return;
}
@@ -163,19 +173,20 @@
}
}
+ @NonNull
public static String name() {
return "ClickModifier";
}
- public static void apply(WireBuffer buffer) {
+ public static void apply(@NonNull WireBuffer buffer) {
buffer.start(OP_CODE);
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(WireBuffer buffer, @NonNull List<Operation> operations) {
operations.add(new ClickModifierOperation());
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Layout Operations", OP_CODE, name())
.description(
"Click modifier. This operation contains"
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/Component.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/Component.java
index 96dffca..f4f4ee2 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/Component.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/Component.java
@@ -15,6 +15,9 @@
*/
package com.android.internal.widget.remotecompose.core.operations.layout;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
import com.android.internal.widget.remotecompose.core.CoreDocument;
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.PaintContext;
@@ -31,7 +34,6 @@
import com.android.internal.widget.remotecompose.core.operations.layout.measure.ComponentMeasure;
import com.android.internal.widget.remotecompose.core.operations.layout.measure.Measurable;
import com.android.internal.widget.remotecompose.core.operations.layout.measure.MeasurePass;
-import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.ComponentModifiers;
import com.android.internal.widget.remotecompose.core.operations.paint.PaintBundle;
import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer;
@@ -52,16 +54,23 @@
protected int mAnimationId = -1;
public Visibility mVisibility = Visibility.VISIBLE;
public Visibility mScheduledVisibility = Visibility.VISIBLE;
- public ArrayList<Operation> mList = new ArrayList<>();
+ @NonNull public ArrayList<Operation> mList = new ArrayList<>();
public PaintOperation mPreTranslate;
public boolean mNeedsMeasure = true;
public boolean mNeedsRepaint = false;
- public AnimateMeasure mAnimateMeasure;
- public AnimationSpec mAnimationSpec = new AnimationSpec();
+ @Nullable public AnimateMeasure mAnimateMeasure;
+ @NonNull public AnimationSpec mAnimationSpec = new AnimationSpec();
public boolean mFirstLayout = true;
- PaintBundle mPaint = new PaintBundle();
- protected HashSet<ComponentValue> mComponentValues = new HashSet<>();
+ @NonNull PaintBundle mPaint = new PaintBundle();
+ @NonNull protected HashSet<ComponentValue> mComponentValues = new HashSet<>();
+ protected float mZIndex = 0f;
+
+ public float getZIndex() {
+ return mZIndex;
+ }
+
+ @NonNull
public ArrayList<Operation> getList() {
return mList;
}
@@ -115,7 +124,7 @@
*
* @param context the current context
*/
- private void updateComponentValues(RemoteContext context) {
+ private void updateComponentValues(@NonNull RemoteContext context) {
if (DEBUG) {
System.out.println(
"UPDATE COMPONENT VALUES ("
@@ -172,7 +181,7 @@
this(parent, componentId, -1, x, y, width, height);
}
- public Component(Component component) {
+ public Component(@NonNull Component component) {
this(
component.mParent,
component.mComponentId,
@@ -212,7 +221,10 @@
*
* @param context the current context
*/
- public void updateVariables(RemoteContext context) {
+ public void updateVariables(@NonNull RemoteContext context) {
+ Component prev = context.lastComponent;
+ context.lastComponent = this;
+
if (!mComponentValues.isEmpty()) {
updateComponentValues(context);
}
@@ -224,6 +236,7 @@
o.apply(context);
}
}
+ context.lastComponent = prev;
}
public void addComponentValue(ComponentValue v) {
@@ -283,14 +296,14 @@
float maxWidth,
float minHeight,
float maxHeight,
- MeasurePass measure) {
+ @NonNull MeasurePass measure) {
ComponentMeasure m = measure.get(this);
m.setW(mWidth);
m.setH(mHeight);
}
@Override
- public void layout(RemoteContext context, MeasurePass measure) {
+ public void layout(@NonNull RemoteContext context, @NonNull MeasurePass measure) {
ComponentMeasure m = measure.get(this);
if (!mFirstLayout
&& context.isAnimationEnabled()
@@ -332,7 +345,7 @@
mFirstLayout = false;
}
- public float[] locationInWindow = new float[2];
+ @NonNull public float[] locationInWindow = new float[2];
public boolean contains(float x, float y) {
locationInWindow[0] = 0f;
@@ -353,13 +366,57 @@
if (op instanceof Component) {
((Component) op).onClick(context, document, x, y);
}
- if (op instanceof ComponentModifiers) {
- ((ComponentModifiers) op).onClick(context, document, this, x, y);
+ if (op instanceof ClickHandler) {
+ ((ClickHandler) op).onClick(context, document, this, x, y);
}
}
}
- public void getLocationInWindow(float[] value) {
+ public void onTouchDown(RemoteContext context, CoreDocument document, float x, float y) {
+ if (!contains(x, y)) {
+ return;
+ }
+ for (Operation op : mList) {
+ if (op instanceof Component) {
+ ((Component) op).onTouchDown(context, document, x, y);
+ }
+ if (op instanceof TouchHandler) {
+ ((TouchHandler) op).onTouchDown(context, document, this, x, y);
+ }
+ }
+ }
+
+ public void onTouchUp(
+ RemoteContext context, CoreDocument document, float x, float y, boolean force) {
+ if (!force && !contains(x, y)) {
+ return;
+ }
+ for (Operation op : mList) {
+ if (op instanceof Component) {
+ ((Component) op).onTouchUp(context, document, x, y, force);
+ }
+ if (op instanceof TouchHandler) {
+ ((TouchHandler) op).onTouchUp(context, document, this, x, y);
+ }
+ }
+ }
+
+ public void onTouchCancel(
+ RemoteContext context, CoreDocument document, float x, float y, boolean force) {
+ if (!force && !contains(x, y)) {
+ return;
+ }
+ for (Operation op : mList) {
+ if (op instanceof Component) {
+ ((Component) op).onTouchCancel(context, document, x, y, force);
+ }
+ if (op instanceof TouchHandler) {
+ ((TouchHandler) op).onTouchCancel(context, document, this, x, y);
+ }
+ }
+ }
+
+ public void getLocationInWindow(@NonNull float[] value) {
value[0] += mX;
value[1] += mY;
if (mParent != null) {
@@ -372,6 +429,7 @@
}
}
+ @NonNull
@Override
public String toString() {
return "COMPONENT(<"
@@ -393,14 +451,14 @@
+ ") ";
}
+ @NonNull
protected String getSerializedName() {
return "COMPONENT";
}
@Override
- public void serializeToString(int indent, StringSerializer serializer) {
- serializer.append(
- indent,
+ public void serializeToString(int indent, @NonNull StringSerializer serializer) {
+ String content =
getSerializedName()
+ " ["
+ mComponentId
@@ -416,9 +474,9 @@
+ ", "
+ mHeight
+ "] "
- + mVisibility
- // + " [" + mNeedsMeasure + ", " + mNeedsRepaint + "]"
- );
+ + mVisibility;
+ // + " [" + mNeedsMeasure + ", " + mNeedsRepaint + "]"
+ serializer.append(indent, content);
}
@Override
@@ -427,6 +485,7 @@
}
/** Returns the top-level RootLayoutComponent */
+ @NonNull
public RootLayoutComponent getRoot() throws Exception {
if (this instanceof RootLayoutComponent) {
return (RootLayoutComponent) this;
@@ -441,6 +500,7 @@
return (RootLayoutComponent) p;
}
+ @NonNull
@Override
public String deepToString(String indent) {
StringBuilder builder = new StringBuilder();
@@ -477,6 +537,7 @@
}
}
+ @NonNull
public String content() {
StringBuilder builder = new StringBuilder();
for (Operation op : mList) {
@@ -487,6 +548,7 @@
return builder.toString();
}
+ @NonNull
public String textContent() {
StringBuilder builder = new StringBuilder();
for (Operation ignored : mList) {
@@ -499,7 +561,7 @@
return builder.toString();
}
- public void debugBox(Component component, PaintContext context) {
+ public void debugBox(@NonNull Component component, @NonNull PaintContext context) {
float width = component.mWidth;
float height = component.mHeight;
@@ -536,13 +598,15 @@
return 0f;
}
- public void paintingComponent(PaintContext context) {
+ public void paintingComponent(@NonNull PaintContext context) {
if (mPreTranslate != null) {
mPreTranslate.paint(context);
}
+ Component prev = context.getContext().lastComponent;
+ context.getContext().lastComponent = this;
context.save();
context.translate(mX, mY);
- if (context.isDebug()) {
+ if (context.isVisualDebug()) {
debugBox(this, context);
}
for (Operation op : mList) {
@@ -554,9 +618,10 @@
}
}
context.restore();
+ context.getContext().lastComponent = prev;
}
- public boolean applyAnimationAsNeeded(PaintContext context) {
+ public boolean applyAnimationAsNeeded(@NonNull PaintContext context) {
if (context.isAnimationEnabled() && mAnimateMeasure != null) {
mAnimateMeasure.apply(context);
needsRepaint();
@@ -566,8 +631,8 @@
}
@Override
- public void paint(PaintContext context) {
- if (context.isDebug()) {
+ public void paint(@NonNull PaintContext context) {
+ if (context.isVisualDebug()) {
context.save();
context.translate(mX, mY);
context.savePaint();
@@ -594,7 +659,7 @@
paintingComponent(context);
}
- public void getComponents(ArrayList<Component> components) {
+ public void getComponents(@NonNull ArrayList<Component> components) {
for (Operation op : mList) {
if (op instanceof Component) {
components.add((Component) op);
@@ -602,7 +667,7 @@
}
}
- public void getData(ArrayList<TextData> data) {
+ public void getData(@NonNull ArrayList<TextData> data) {
for (Operation op : mList) {
if (op instanceof TextData) {
data.add((TextData) op);
@@ -631,6 +696,7 @@
return mNeedsRepaint;
}
+ @Nullable
public Component getComponent(int cid) {
if (mComponentId == cid || mAnimationId == cid) {
return this;
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ComponentEnd.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ComponentEnd.java
index c83ee487..f370e20 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ComponentEnd.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ComponentEnd.java
@@ -15,6 +15,9 @@
*/
package com.android.internal.widget.remotecompose.core.operations.layout;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.RemoteContext;
@@ -26,10 +29,11 @@
public class ComponentEnd implements Operation {
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(buffer);
}
+ @NonNull
@Override
public String toString() {
return "COMPONENT_END";
@@ -40,11 +44,13 @@
// nothing
}
+ @NonNull
@Override
- public String deepToString(String indent) {
+ public String deepToString(@Nullable String indent) {
return (indent != null ? indent : "") + toString();
}
+ @NonNull
public static String name() {
return "ComponentEnd";
}
@@ -53,7 +59,7 @@
return Operations.COMPONENT_END;
}
- public static void apply(WireBuffer buffer) {
+ public static void apply(@NonNull WireBuffer buffer) {
buffer.start(Operations.COMPONENT_END);
}
@@ -61,11 +67,11 @@
return 1 + 4 + 4 + 4;
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(WireBuffer buffer, @NonNull List<Operation> operations) {
operations.add(new ComponentEnd());
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Layout Operations", id(), name())
.description(
"End tag for components / layouts. This operation marks the end"
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ComponentStart.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ComponentStart.java
index 72cc9b6..f250d9a 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ComponentStart.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ComponentStart.java
@@ -18,6 +18,9 @@
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.FLOAT;
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.RemoteContext;
@@ -69,10 +72,11 @@
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(buffer, mType, mComponentId, mWidth, mHeight);
}
+ @NonNull
@Override
public String toString() {
return "COMPONENT_START (type "
@@ -90,8 +94,9 @@
+ ")";
}
+ @NonNull
@Override
- public String deepToString(String indent) {
+ public String deepToString(@Nullable String indent) {
return (indent != null ? indent : "") + toString();
}
@@ -119,6 +124,7 @@
public static final int LAYOUT_ROW = 15;
public static final int LAYOUT_COLUMN = 16;
+ @NonNull
public static String typeDescription(int type) {
switch (type) {
case DEFAULT:
@@ -152,6 +158,7 @@
}
}
+ @NonNull
public static String name() {
return "ComponentStart";
}
@@ -161,7 +168,7 @@
}
public static void apply(
- WireBuffer buffer, int type, int componentId, float width, float height) {
+ @NonNull WireBuffer buffer, int type, int componentId, float width, float height) {
buffer.start(Operations.COMPONENT_START);
buffer.writeInt(type);
buffer.writeInt(componentId);
@@ -173,7 +180,7 @@
return 1 + 4 + 4 + 4;
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int type = buffer.readInt();
int componentId = buffer.readInt();
float width = buffer.readFloat();
@@ -181,7 +188,7 @@
operations.add(new ComponentStart(type, componentId, width, height));
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Layout Operations", id(), name())
.description(
"Basic component encapsulating draw commands." + "This is not resizable.")
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/DecoratorComponent.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/DecoratorComponent.java
index 314650f..bb43119 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/DecoratorComponent.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/DecoratorComponent.java
@@ -15,7 +15,6 @@
*/
package com.android.internal.widget.remotecompose.core.operations.layout;
-import com.android.internal.widget.remotecompose.core.CoreDocument;
import com.android.internal.widget.remotecompose.core.RemoteContext;
/**
@@ -24,7 +23,4 @@
*/
public interface DecoratorComponent {
void layout(RemoteContext context, float width, float height);
-
- void onClick(
- RemoteContext context, CoreDocument document, Component component, float x, float y);
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LayoutComponent.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LayoutComponent.java
index 8172502..e0923dfb 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LayoutComponent.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LayoutComponent.java
@@ -15,6 +15,9 @@
*/
package com.android.internal.widget.remotecompose.core.operations.layout;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.PaintContext;
import com.android.internal.widget.remotecompose.core.operations.BitmapData;
@@ -25,18 +28,22 @@
import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.ComponentModifiers;
import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.ComponentVisibilityOperation;
import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.DimensionModifierOperation;
+import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.GraphicsLayerModifierOperation;
import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.HeightModifierOperation;
import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.ModifierOperation;
import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.PaddingModifierOperation;
import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.WidthModifierOperation;
+import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.ZIndexModifierOperation;
import java.util.ArrayList;
/** Component with modifiers and children */
public class LayoutComponent extends Component {
- protected WidthModifierOperation mWidthModifier = null;
- protected HeightModifierOperation mHeightModifier = null;
+ @Nullable protected WidthModifierOperation mWidthModifier = null;
+ @Nullable protected HeightModifierOperation mHeightModifier = null;
+ @Nullable protected ZIndexModifierOperation mZIndexModifier = null;
+ @Nullable protected GraphicsLayerModifierOperation mGraphicsLayerModifier = null;
// Margins
protected float mMarginLeft = 0f;
@@ -49,8 +56,10 @@
protected float mPaddingTop = 0f;
protected float mPaddingBottom = 0f;
- protected ComponentModifiers mComponentModifiers = new ComponentModifiers();
- protected ArrayList<Component> mChildrenComponents = new ArrayList<>();
+ @NonNull protected ComponentModifiers mComponentModifiers = new ComponentModifiers();
+ @NonNull protected ArrayList<Component> mChildrenComponents = new ArrayList<>();
+
+ protected boolean mChildrenHaveZIndex = false;
public LayoutComponent(
Component parent,
@@ -95,15 +104,25 @@
return mPaddingBottom;
}
+ @Nullable
public WidthModifierOperation getWidthModifier() {
return mWidthModifier;
}
+ @Nullable
public HeightModifierOperation getHeightModifier() {
return mHeightModifier;
}
- protected LayoutComponentContent mContent = null;
+ @Override
+ public float getZIndex() {
+ if (mZIndexModifier != null) {
+ return mZIndexModifier.getValue();
+ }
+ return mZIndex;
+ }
+
+ @Nullable protected LayoutComponentContent mContent = null;
// Should be removed after ImageLayout is in
private static final boolean USE_IMAGE_TEMP_FIX = true;
@@ -164,6 +183,9 @@
for (Component c : mChildrenComponents) {
c.mParent = this;
mList.add(c);
+ if (c instanceof LayoutComponent && ((LayoutComponent) c).mZIndexModifier != null) {
+ mChildrenHaveZIndex = true;
+ }
}
mX = 0f;
@@ -209,6 +231,12 @@
mHeightModifier = (HeightModifierOperation) op;
applyVerticalMargin = false;
}
+ if (op instanceof ZIndexModifierOperation) {
+ mZIndexModifier = (ZIndexModifierOperation) op;
+ }
+ if (op instanceof GraphicsLayerModifierOperation) {
+ mGraphicsLayerModifier = (GraphicsLayerModifierOperation) op;
+ }
}
if (mWidthModifier == null) {
mWidthModifier = new WidthModifierOperation(DimensionModifierOperation.Type.WRAP);
@@ -220,24 +248,64 @@
setHeight(computeModifierDefinedHeight());
}
+ @NonNull
@Override
public String toString() {
return "UNKNOWN LAYOUT_COMPONENT";
}
@Override
- public void paintingComponent(PaintContext context) {
+ public void paintingComponent(@NonNull PaintContext context) {
+ Component prev = context.getContext().lastComponent;
+ context.getContext().lastComponent = this;
context.save();
context.translate(mX, mY);
+ if (mGraphicsLayerModifier != null) {
+ context.startGraphicsLayer((int) getWidth(), (int) getHeight());
+ float scaleX = mGraphicsLayerModifier.getScaleX();
+ float scaleY = mGraphicsLayerModifier.getScaleY();
+ float rotationX = mGraphicsLayerModifier.getRotationX();
+ float rotationY = mGraphicsLayerModifier.getRotationY();
+ float rotationZ = mGraphicsLayerModifier.getRotationZ();
+ float shadowElevation = mGraphicsLayerModifier.getShadowElevation();
+ float transformOriginX = mGraphicsLayerModifier.getTransformOriginX();
+ float transformOriginY = mGraphicsLayerModifier.getTransformOriginY();
+ float alpha = mGraphicsLayerModifier.getAlpha();
+ int renderEffectId = mGraphicsLayerModifier.getRenderEffectId();
+ context.setGraphicsLayer(
+ scaleX,
+ scaleY,
+ rotationX,
+ rotationY,
+ rotationZ,
+ shadowElevation,
+ transformOriginX,
+ transformOriginY,
+ alpha,
+ renderEffectId);
+ }
mComponentModifiers.paint(context);
float tx = mPaddingLeft;
float ty = mPaddingTop;
context.translate(tx, ty);
- for (Component child : mChildrenComponents) {
- child.paint(context);
+ if (mChildrenHaveZIndex) {
+ // TODO -- should only sort when something has changed
+ ArrayList<Component> sorted = new ArrayList<Component>(mChildrenComponents);
+ sorted.sort((a, b) -> (int) (a.getZIndex() - b.getZIndex()));
+ for (Component child : sorted) {
+ child.paint(context);
+ }
+ } else {
+ for (Component child : mChildrenComponents) {
+ child.paint(context);
+ }
+ }
+ if (mGraphicsLayerModifier != null) {
+ context.endGraphicsLayer();
}
context.translate(-tx, -ty);
context.restore();
+ context.getContext().lastComponent = prev;
}
/** Traverse the modifiers to compute indicated dimension */
@@ -248,7 +316,8 @@
for (Operation c : mComponentModifiers.getList()) {
if (c instanceof WidthModifierOperation) {
WidthModifierOperation o = (WidthModifierOperation) c;
- if (o.getType() == DimensionModifierOperation.Type.EXACT) {
+ if (o.getType() == DimensionModifierOperation.Type.EXACT
+ || o.getType() == DimensionModifierOperation.Type.EXACT_DP) {
w = o.getValue();
}
break;
@@ -291,7 +360,8 @@
for (Operation c : mComponentModifiers.getList()) {
if (c instanceof HeightModifierOperation) {
HeightModifierOperation o = (HeightModifierOperation) c;
- if (o.getType() == DimensionModifierOperation.Type.EXACT) {
+ if (o.getType() == DimensionModifierOperation.Type.EXACT
+ || o.getType() == DimensionModifierOperation.Type.EXACT_DP) {
h = o.getValue();
}
break;
@@ -326,6 +396,7 @@
return t + b;
}
+ @NonNull
public ArrayList<Component> getChildrenComponents() {
return mChildrenComponents;
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LayoutComponentContent.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LayoutComponentContent.java
index 66fd053..0a085b4 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LayoutComponentContent.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LayoutComponentContent.java
@@ -17,6 +17,8 @@
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.WireBuffer;
@@ -38,6 +40,7 @@
super(parent, componentId, animationId, x, y, width, height);
}
+ @NonNull
public static String name() {
return "LayoutContent";
}
@@ -46,22 +49,23 @@
return Operations.LAYOUT_CONTENT;
}
+ @NonNull
@Override
protected String getSerializedName() {
return "CONTENT";
}
- public static void apply(WireBuffer buffer, int componentId) {
+ public static void apply(@NonNull WireBuffer buffer, int componentId) {
buffer.start(Operations.LAYOUT_CONTENT);
buffer.writeInt(componentId);
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int componentId = buffer.readInt();
operations.add(new LayoutComponentContent(componentId, 0, 0, 0, 0, null, -1));
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Layout Operations", id(), name())
.field(INT, "COMPONENT_ID", "unique id for this component")
.description(
@@ -71,7 +75,7 @@
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(buffer, mComponentId);
}
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ListActionsOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ListActionsOperation.java
new file mode 100644
index 0000000..c4df075
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ListActionsOperation.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2024 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.internal.widget.remotecompose.core.operations.layout;
+
+import com.android.internal.widget.remotecompose.core.CoreDocument;
+import com.android.internal.widget.remotecompose.core.Operation;
+import com.android.internal.widget.remotecompose.core.PaintContext;
+import com.android.internal.widget.remotecompose.core.PaintOperation;
+import com.android.internal.widget.remotecompose.core.RemoteContext;
+import com.android.internal.widget.remotecompose.core.operations.TextData;
+import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.ModifierOperation;
+import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer;
+
+import java.util.ArrayList;
+
+public abstract class ListActionsOperation extends PaintOperation
+ implements ModifierOperation, DecoratorComponent {
+
+ String mOperationName;
+ float mWidth = 0;
+ float mHeight = 0;
+
+ private final float[] mLocationInWindow = new float[2];
+
+ public ListActionsOperation(String operationName) {
+ mOperationName = operationName;
+ }
+
+ public ArrayList<Operation> mList = new ArrayList<>();
+
+ public ArrayList<Operation> getList() {
+ return mList;
+ }
+
+ @Override
+ public String toString() {
+ return mOperationName;
+ }
+
+ @Override
+ public void apply(RemoteContext context) {
+ for (Operation op : mList) {
+ if (op instanceof TextData) {
+ op.apply(context);
+ }
+ }
+ }
+
+ @Override
+ public String deepToString(String indent) {
+ return (indent != null ? indent : "") + toString();
+ }
+
+ @Override
+ public void paint(PaintContext context) {}
+
+ @Override
+ public void layout(RemoteContext context, float width, float height) {
+ mWidth = width;
+ mHeight = height;
+ }
+
+ @Override
+ public void serializeToString(int indent, StringSerializer serializer) {
+ serializer.append(indent, mOperationName);
+ for (Operation o : mList) {
+ if (o instanceof ActionOperation) {
+ ((ActionOperation) o).serializeToString(indent + 1, serializer);
+ }
+ }
+ }
+
+ public boolean applyActions(
+ RemoteContext context,
+ CoreDocument document,
+ Component component,
+ float x,
+ float y,
+ boolean force) {
+ if (!force && !component.isVisible()) {
+ return false;
+ }
+ if (!force && !component.contains(x, y)) {
+ return false;
+ }
+ mLocationInWindow[0] = 0f;
+ mLocationInWindow[1] = 0f;
+ component.getLocationInWindow(mLocationInWindow);
+ for (Operation o : mList) {
+ if (o instanceof ActionOperation) {
+ ((ActionOperation) o).runAction(context, document, component, x, y);
+ }
+ }
+ return true;
+ }
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LoopEnd.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LoopEnd.java
index 3086d6a..c90077b 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LoopEnd.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LoopEnd.java
@@ -15,6 +15,9 @@
*/
package com.android.internal.widget.remotecompose.core.operations.layout;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.RemoteContext;
@@ -26,10 +29,11 @@
public class LoopEnd implements Operation {
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(buffer);
}
+ @NonNull
@Override
public String toString() {
return "LOOP_END";
@@ -40,11 +44,13 @@
// nothing
}
+ @NonNull
@Override
- public String deepToString(String indent) {
+ public String deepToString(@Nullable String indent) {
return (indent != null ? indent : "") + toString();
}
+ @NonNull
public static String name() {
return "LoopEnd";
}
@@ -53,15 +59,15 @@
return Operations.LOOP_END;
}
- public static void apply(WireBuffer buffer) {
+ public static void apply(@NonNull WireBuffer buffer) {
buffer.start(id());
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(WireBuffer buffer, @NonNull List<Operation> operations) {
operations.add(new LoopEnd());
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Operations", id(), name()).description("End tag for loops");
}
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LoopOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LoopOperation.java
index 6910008..eeaeafd 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LoopOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LoopOperation.java
@@ -15,6 +15,9 @@
*/
package com.android.internal.widget.remotecompose.core.operations.layout;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.PaintContext;
@@ -30,7 +33,7 @@
public class LoopOperation extends PaintOperation {
private static final int OP_CODE = Operations.LOOP_START;
- public ArrayList<Operation> mList = new ArrayList<>();
+ @NonNull public ArrayList<Operation> mList = new ArrayList<>();
int mIndexVariableId;
float mUntil = 12;
@@ -49,27 +52,30 @@
mIndexVariableId = indexId;
}
+ @NonNull
public ArrayList<Operation> getList() {
return mList;
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(buffer, mUntil, mFrom, mStep, mIndexVariableId);
}
+ @NonNull
@Override
public String toString() {
return "LoopOperation";
}
+ @NonNull
@Override
- public String deepToString(String indent) {
+ public String deepToString(@Nullable String indent) {
return (indent != null ? indent : "") + toString();
}
@Override
- public void paint(PaintContext context) {
+ public void paint(@NonNull PaintContext context) {
if (mIndexVariableId == 0) {
for (float i = mFrom; i < mUntil; i += mStep) {
for (Operation op : mList) {
@@ -89,11 +95,13 @@
}
}
+ @NonNull
public static String name() {
return "Loop";
}
- public static void apply(WireBuffer buffer, float count, float from, float step, int indexId) {
+ public static void apply(
+ @NonNull WireBuffer buffer, float count, float from, float step, int indexId) {
buffer.start(OP_CODE);
buffer.writeFloat(count);
buffer.writeFloat(from);
@@ -101,7 +109,7 @@
buffer.writeInt(indexId);
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
float count = buffer.readFloat();
float from = buffer.readFloat();
float step = buffer.readFloat();
@@ -109,7 +117,7 @@
operations.add(new LoopOperation(count, from, step, indexId));
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Operations", OP_CODE, name())
.description("Loop. This operation execute" + " a list of action in a loop");
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ClickModifierEnd.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/OperationsListEnd.java
similarity index 68%
rename from core/java/com/android/internal/widget/remotecompose/core/operations/layout/ClickModifierEnd.java
rename to core/java/com/android/internal/widget/remotecompose/core/operations/layout/OperationsListEnd.java
index fe726ac..bd8d1f0 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ClickModifierEnd.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/OperationsListEnd.java
@@ -15,6 +15,9 @@
*/
package com.android.internal.widget.remotecompose.core.operations.layout;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.RemoteContext;
@@ -23,16 +26,17 @@
import java.util.List;
-public class ClickModifierEnd implements Operation {
+public class OperationsListEnd implements Operation {
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(buffer);
}
+ @NonNull
@Override
public String toString() {
- return "CLICK_END";
+ return "LIST_END";
}
@Override
@@ -40,31 +44,31 @@
// nothing
}
+ @NonNull
@Override
- public String deepToString(String indent) {
+ public String deepToString(@Nullable String indent) {
return (indent != null ? indent : "") + toString();
}
+ @NonNull
public static String name() {
- return "ClickModifierEnd";
+ return "ListEnd";
}
public static int id() {
- return Operations.MODIFIER_CLICK_END;
+ return Operations.OPERATIONS_LIST_END;
}
- public static void apply(WireBuffer buffer) {
+ public static void apply(@NonNull WireBuffer buffer) {
buffer.start(id());
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
- operations.add(new ClickModifierEnd());
+ public static void read(WireBuffer buffer, @NonNull List<Operation> operations) {
+ operations.add(new OperationsListEnd());
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Layout Operations", id(), name())
- .description(
- "End tag for click modifiers. This operation marks the end"
- + "of a click modifier");
+ .description("End tag for list of operations.");
}
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/RootLayoutComponent.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/RootLayoutComponent.java
index 680bb0b..524ae59 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/RootLayoutComponent.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/RootLayoutComponent.java
@@ -17,6 +17,8 @@
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.PaintContext;
@@ -34,7 +36,8 @@
/** Represents the root layout component. Entry point to the component tree layout/paint. */
public class RootLayoutComponent extends Component implements ComponentStartOperation {
- int mCurrentId = -1;
+ private int mCurrentId = -1;
+ private boolean mHasTouchListeners = false;
public RootLayoutComponent(
int componentId,
@@ -52,6 +55,7 @@
super(parent, componentId, -1, x, y, width, height);
}
+ @NonNull
@Override
public String toString() {
return "ROOT "
@@ -69,7 +73,7 @@
}
@Override
- public void serializeToString(int indent, StringSerializer serializer) {
+ public void serializeToString(int indent, @NonNull StringSerializer serializer) {
serializer.append(
indent,
"ROOT ["
@@ -89,6 +93,15 @@
}
/**
+ * Set the flag to traverse the tree when touch events happen
+ *
+ * @param value true to indicate that the tree has touch listeners
+ */
+ public void setHasTouchListeners(boolean value) {
+ mHasTouchListeners = value;
+ }
+
+ /**
* Traverse the hierarchy and assign generated ids to component without ids. Most components
* would already have ids assigned during the document creation, but this allow us to take care
* of any components added during the inflation.
@@ -100,7 +113,7 @@
assignId(this);
}
- private void assignId(Component component) {
+ private void assignId(@NonNull Component component) {
if (component.mComponentId == -1) {
mCurrentId--;
component.mComponentId = mCurrentId;
@@ -113,7 +126,7 @@
}
/** This will measure then layout the tree of components */
- public void layout(RemoteContext context) {
+ public void layout(@NonNull RemoteContext context) {
if (!mNeedsMeasure) {
return;
}
@@ -134,7 +147,7 @@
}
@Override
- public void paint(PaintContext context) {
+ public void paint(@NonNull PaintContext context) {
mNeedsRepaint = false;
context.getContext().lastComponent = this;
context.save();
@@ -152,13 +165,15 @@
context.restore();
}
+ @NonNull
public String displayHierarchy() {
StringSerializer serializer = new StringSerializer();
displayHierarchy(this, 0, serializer);
return serializer.toString();
}
- public void displayHierarchy(Component component, int indent, StringSerializer serializer) {
+ public void displayHierarchy(
+ @NonNull Component component, int indent, @NonNull StringSerializer serializer) {
component.serializeToString(indent, serializer);
for (Operation c : component.mList) {
if (c instanceof ComponentModifiers) {
@@ -171,6 +186,7 @@
}
}
+ @NonNull
public static String name() {
return "RootLayout";
}
@@ -179,17 +195,17 @@
return Operations.LAYOUT_ROOT;
}
- public static void apply(WireBuffer buffer, int componentId) {
+ public static void apply(@NonNull WireBuffer buffer, int componentId) {
buffer.start(Operations.LAYOUT_ROOT);
buffer.writeInt(componentId);
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int componentId = buffer.readInt();
operations.add(new RootLayoutComponent(componentId, 0, 0, 0, 0, null, -1));
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Layout Operations", id(), name())
.field(INT, "COMPONENT_ID", "unique id for this component")
.description(
@@ -199,7 +215,11 @@
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(buffer, mComponentId);
}
+
+ public boolean hasTouchListeners() {
+ return mHasTouchListeners;
+ }
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/TouchCancelModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/TouchCancelModifierOperation.java
new file mode 100644
index 0000000..486efbd
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/TouchCancelModifierOperation.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2024 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.internal.widget.remotecompose.core.operations.layout;
+
+import com.android.internal.widget.remotecompose.core.CoreDocument;
+import com.android.internal.widget.remotecompose.core.Operation;
+import com.android.internal.widget.remotecompose.core.Operations;
+import com.android.internal.widget.remotecompose.core.RemoteContext;
+import com.android.internal.widget.remotecompose.core.WireBuffer;
+import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder;
+
+import java.util.List;
+
+/** Represents a touch cancel modifier + actions */
+public class TouchCancelModifierOperation extends ListActionsOperation implements TouchHandler {
+
+ private static final int OP_CODE = Operations.MODIFIER_TOUCH_CANCEL;
+
+ public TouchCancelModifierOperation() {
+ super("TOUCH_CANCEL_MODIFIER");
+ }
+
+ @Override
+ public void write(WireBuffer buffer) {
+ apply(buffer);
+ }
+
+ @Override
+ public String toString() {
+ return "TouchCancelModifier";
+ }
+
+ @Override
+ public void apply(RemoteContext context) {
+ RootLayoutComponent root = context.getDocument().getRootLayoutComponent();
+ if (root != null) {
+ root.setHasTouchListeners(true);
+ }
+ super.apply(context);
+ }
+
+ @Override
+ public void onTouchDown(
+ RemoteContext context, CoreDocument document, Component component, float x, float y) {
+ // nothing
+ }
+
+ @Override
+ public void onTouchUp(
+ RemoteContext context, CoreDocument document, Component component, float x, float y) {
+ // nothing
+ }
+
+ @Override
+ public void onTouchCancel(
+ RemoteContext context, CoreDocument document, Component component, float x, float y) {
+ applyActions(context, document, component, x, y, true);
+ }
+
+ public static String name() {
+ return "TouchCancelModifier";
+ }
+
+ public static void apply(WireBuffer buffer) {
+ buffer.start(OP_CODE);
+ }
+
+ public static void read(WireBuffer buffer, List<Operation> operations) {
+ operations.add(new TouchCancelModifierOperation());
+ }
+
+ public static void documentation(DocumentationBuilder doc) {
+ doc.operation("Modifier Operations", OP_CODE, name())
+ .description(
+ "Touch cancel modifier. This operation contains"
+ + " a list of action executed on Touch cancel");
+ }
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/TouchDownModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/TouchDownModifierOperation.java
new file mode 100644
index 0000000..5d379fe
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/TouchDownModifierOperation.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2024 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.internal.widget.remotecompose.core.operations.layout;
+
+import com.android.internal.widget.remotecompose.core.CoreDocument;
+import com.android.internal.widget.remotecompose.core.Operation;
+import com.android.internal.widget.remotecompose.core.Operations;
+import com.android.internal.widget.remotecompose.core.RemoteContext;
+import com.android.internal.widget.remotecompose.core.WireBuffer;
+import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder;
+
+import java.util.List;
+
+/** Represents a touch down modifier + actions */
+public class TouchDownModifierOperation extends ListActionsOperation implements TouchHandler {
+
+ private static final int OP_CODE = Operations.MODIFIER_TOUCH_DOWN;
+
+ public TouchDownModifierOperation() {
+ super("TOUCH_DOWN_MODIFIER");
+ }
+
+ @Override
+ public void write(WireBuffer buffer) {
+ apply(buffer);
+ }
+
+ @Override
+ public String toString() {
+ return "TouchDownModifier";
+ }
+
+ @Override
+ public void apply(RemoteContext context) {
+ RootLayoutComponent root = context.getDocument().getRootLayoutComponent();
+ if (root != null) {
+ root.setHasTouchListeners(true);
+ }
+ super.apply(context);
+ }
+
+ @Override
+ public void onTouchDown(
+ RemoteContext context, CoreDocument document, Component component, float x, float y) {
+ if (applyActions(context, document, component, x, y, false)) {
+ document.appliedTouchOperation(component);
+ }
+ }
+
+ @Override
+ public void onTouchUp(
+ RemoteContext context, CoreDocument document, Component component, float x, float y) {
+ // nothing
+ }
+
+ @Override
+ public void onTouchCancel(
+ RemoteContext context, CoreDocument document, Component component, float x, float y) {
+ // nothing
+ }
+
+ public static String name() {
+ return "TouchModifier";
+ }
+
+ public static void apply(WireBuffer buffer) {
+ buffer.start(OP_CODE);
+ }
+
+ public static void read(WireBuffer buffer, List<Operation> operations) {
+ operations.add(new TouchDownModifierOperation());
+ }
+
+ public static void documentation(DocumentationBuilder doc) {
+ doc.operation("Modifier Operations", OP_CODE, name())
+ .description(
+ "Touch down modifier. This operation contains"
+ + " a list of action executed on Touch down");
+ }
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/TouchHandler.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/TouchHandler.java
new file mode 100644
index 0000000..5adfc33
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/TouchHandler.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2024 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.internal.widget.remotecompose.core.operations.layout;
+
+import com.android.internal.widget.remotecompose.core.CoreDocument;
+import com.android.internal.widget.remotecompose.core.RemoteContext;
+
+/** Interface to represent operations that can handle touch events */
+public interface TouchHandler {
+
+ /**
+ * callback for a touch down event
+ *
+ * @param context the current context
+ * @param document the current document
+ * @param component the component on which the touch has been received
+ * @param x the x position of the click in document coordinates
+ * @param y the y position of the click in document coordinates
+ */
+ void onTouchDown(
+ RemoteContext context, CoreDocument document, Component component, float x, float y);
+
+ /**
+ * callback for a touch up event
+ *
+ * @param context the current context
+ * @param document the current document
+ * @param component the component on which the touch has been received
+ * @param x the x position of the click in document coordinates
+ * @param y the y position of the click in document coordinates
+ */
+ void onTouchUp(
+ RemoteContext context, CoreDocument document, Component component, float x, float y);
+
+ /**
+ * callback for a touch cancel event
+ *
+ * @param context the current context
+ * @param document the current document
+ * @param component the component on which the touch has been received
+ * @param x the x position of the click in document coordinates
+ * @param y the y position of the click in document coordinates
+ */
+ void onTouchCancel(
+ RemoteContext context, CoreDocument document, Component component, float x, float y);
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/TouchUpModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/TouchUpModifierOperation.java
new file mode 100644
index 0000000..263cc43
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/TouchUpModifierOperation.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2024 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.internal.widget.remotecompose.core.operations.layout;
+
+import com.android.internal.widget.remotecompose.core.CoreDocument;
+import com.android.internal.widget.remotecompose.core.Operation;
+import com.android.internal.widget.remotecompose.core.Operations;
+import com.android.internal.widget.remotecompose.core.RemoteContext;
+import com.android.internal.widget.remotecompose.core.WireBuffer;
+import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder;
+
+import java.util.List;
+
+/** Represents a touch up modifier + actions */
+public class TouchUpModifierOperation extends ListActionsOperation implements TouchHandler {
+
+ private static final int OP_CODE = Operations.MODIFIER_TOUCH_UP;
+
+ public TouchUpModifierOperation() {
+ super("TOUCH_UP_MODIFIER");
+ }
+
+ @Override
+ public void write(WireBuffer buffer) {
+ apply(buffer);
+ }
+
+ @Override
+ public String toString() {
+ return "TouchUpModifier";
+ }
+
+ @Override
+ public void apply(RemoteContext context) {
+ RootLayoutComponent root = context.getDocument().getRootLayoutComponent();
+ if (root != null) {
+ root.setHasTouchListeners(true);
+ }
+ super.apply(context);
+ }
+
+ @Override
+ public void onTouchDown(
+ RemoteContext context, CoreDocument document, Component component, float x, float y) {
+ // nothing
+ }
+
+ @Override
+ public void onTouchUp(
+ RemoteContext context, CoreDocument document, Component component, float x, float y) {
+ applyActions(context, document, component, x, y, true);
+ }
+
+ @Override
+ public void onTouchCancel(
+ RemoteContext context, CoreDocument document, Component component, float x, float y) {
+ // nothing
+ }
+
+ public static String name() {
+ return "TouchUpModifier";
+ }
+
+ public static void apply(WireBuffer buffer) {
+ buffer.start(OP_CODE);
+ }
+
+ public static void read(WireBuffer buffer, List<Operation> operations) {
+ operations.add(new TouchUpModifierOperation());
+ }
+
+ public static void documentation(DocumentationBuilder doc) {
+ doc.operation("Modifier Operations", OP_CODE, name())
+ .description(
+ "Touch up modifier. This operation contains"
+ + " a list of action executed on Touch up");
+ }
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/AnimateMeasure.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/AnimateMeasure.java
index e450585..6036b74 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/AnimateMeasure.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/AnimateMeasure.java
@@ -15,6 +15,8 @@
*/
package com.android.internal.widget.remotecompose.core.operations.layout.animation;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.PaintContext;
import com.android.internal.widget.remotecompose.core.operations.layout.Component;
@@ -44,18 +46,23 @@
float mP = 0f;
float mVp = 0f;
+
+ @NonNull
FloatAnimation mMotionEasing =
new FloatAnimation(mMotionEasingType, mDuration / 1000f, null, 0f, Float.NaN);
+
+ @NonNull
FloatAnimation mVisibilityEasing =
new FloatAnimation(
mVisibilityEasingType, mDurationVisibilityChange / 1000f, null, 0f, Float.NaN);
+
ParticleAnimation mParticleAnimation;
public AnimateMeasure(
long startTime,
- Component component,
+ @NonNull Component component,
ComponentMeasure original,
- ComponentMeasure target,
+ @NonNull ComponentMeasure target,
int duration,
int durationVisibilityChange,
AnimationSpec.ANIMATION enterAnimation,
@@ -94,9 +101,9 @@
mVp = mVisibilityEasing.get(visibilityProgress);
}
- public PaintBundle paint = new PaintBundle();
+ @NonNull public PaintBundle paint = new PaintBundle();
- public void apply(PaintContext context) {
+ public void apply(@NonNull PaintContext context) {
update(context.getContext().currentTime);
mComponent.setX(getX());
@@ -338,7 +345,7 @@
}
}
- public void updateTarget(ComponentMeasure measure, long currentTime) {
+ public void updateTarget(@NonNull ComponentMeasure measure, long currentTime) {
mOriginal.setX(getX());
mOriginal.setY(getY());
mOriginal.setW(getWidth());
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/AnimationSpec.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/AnimationSpec.java
index 35533cb..47abade 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/AnimationSpec.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/AnimationSpec.java
@@ -17,6 +17,9 @@
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.RemoteContext;
@@ -92,6 +95,7 @@
return mExitAnimation;
}
+ @NonNull
@Override
public String toString() {
return "ANIMATION_SPEC (" + mMotionDuration + " ms)";
@@ -109,7 +113,7 @@
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(
buffer,
mAnimationId,
@@ -126,11 +130,13 @@
// nothing here
}
+ @NonNull
@Override
- public String deepToString(String indent) {
+ public String deepToString(@Nullable String indent) {
return (indent != null ? indent : "") + toString();
}
+ @NonNull
public static String name() {
return "AnimationSpec";
}
@@ -139,10 +145,11 @@
return Operations.ANIMATION_SPEC;
}
- public static int animationToInt(ANIMATION animation) {
+ public static int animationToInt(@NonNull ANIMATION animation) {
return animation.ordinal();
}
+ @NonNull
public static ANIMATION intToAnimation(int value) {
switch (value) {
case 0:
@@ -167,14 +174,14 @@
}
public static void apply(
- WireBuffer buffer,
+ @NonNull WireBuffer buffer,
int animationId,
int motionDuration,
int motionEasingType,
int visibilityDuration,
int visibilityEasingType,
- ANIMATION enterAnimation,
- ANIMATION exitAnimation) {
+ @NonNull ANIMATION enterAnimation,
+ @NonNull ANIMATION exitAnimation) {
buffer.start(Operations.ANIMATION_SPEC);
buffer.writeInt(animationId);
buffer.writeInt(motionDuration);
@@ -185,7 +192,7 @@
buffer.writeInt(animationToInt(exitAnimation));
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int animationId = buffer.readInt();
int motionDuration = buffer.readInt();
int motionEasingType = buffer.readInt();
@@ -205,7 +212,7 @@
operations.add(op);
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Layout Operations", id(), name())
.description("define the animation")
.field(INT, "animationId", "")
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/ParticleAnimation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/ParticleAnimation.java
index 686643f..37d2078 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/ParticleAnimation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/ParticleAnimation.java
@@ -15,6 +15,8 @@
*/
package com.android.internal.widget.remotecompose.core.operations.layout.animation;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.PaintContext;
import com.android.internal.widget.remotecompose.core.operations.layout.Component;
import com.android.internal.widget.remotecompose.core.operations.layout.measure.ComponentMeasure;
@@ -24,14 +26,14 @@
import java.util.HashMap;
public class ParticleAnimation {
- HashMap<Integer, ArrayList<Particle>> mAllParticles = new HashMap<>();
+ @NonNull HashMap<Integer, ArrayList<Particle>> mAllParticles = new HashMap<>();
- PaintBundle mPaint = new PaintBundle();
+ @NonNull PaintBundle mPaint = new PaintBundle();
public void animate(
- PaintContext context,
- Component component,
- ComponentMeasure start,
+ @NonNull PaintContext context,
+ @NonNull Component component,
+ @NonNull ComponentMeasure start,
ComponentMeasure end,
float progress) {
ArrayList<Particle> particles = mAllParticles.get(component.getComponentId());
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/BoxLayout.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/BoxLayout.java
index 047a968..f3e5509 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/BoxLayout.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/BoxLayout.java
@@ -17,6 +17,8 @@
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.PaintContext;
@@ -75,6 +77,7 @@
verticalPositioning);
}
+ @NonNull
@Override
public String toString() {
return "BOX ["
@@ -93,6 +96,7 @@
+ mVisibility;
}
+ @NonNull
@Override
protected String getSerializedName() {
return "BOX";
@@ -100,7 +104,11 @@
@Override
public void computeWrapSize(
- PaintContext context, float maxWidth, float maxHeight, MeasurePass measure, Size size) {
+ PaintContext context,
+ float maxWidth,
+ float maxHeight,
+ @NonNull MeasurePass measure,
+ @NonNull Size size) {
for (Component c : mChildrenComponents) {
c.measure(context, 0f, maxWidth, 0f, maxHeight, measure);
ComponentMeasure m = measure.get(c);
@@ -119,14 +127,14 @@
float maxWidth,
float minHeight,
float maxHeight,
- MeasurePass measure) {
+ @NonNull MeasurePass measure) {
for (Component child : mChildrenComponents) {
child.measure(context, minWidth, maxWidth, minHeight, maxHeight, measure);
}
}
@Override
- public void internalLayoutMeasure(PaintContext context, MeasurePass measure) {
+ public void internalLayoutMeasure(PaintContext context, @NonNull MeasurePass measure) {
ComponentMeasure selfMeasure = measure.get(this);
float selfWidth = selfMeasure.getW() - mPaddingLeft - mPaddingRight;
float selfHeight = selfMeasure.getH() - mPaddingTop - mPaddingBottom;
@@ -161,6 +169,7 @@
}
}
+ @NonNull
public static String name() {
return "BoxLayout";
}
@@ -170,7 +179,7 @@
}
public static void apply(
- WireBuffer buffer,
+ @NonNull WireBuffer buffer,
int componentId,
int animationId,
int horizontalPositioning,
@@ -182,7 +191,7 @@
buffer.writeInt(verticalPositioning);
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int componentId = buffer.readInt();
int animationId = buffer.readInt();
int horizontalPositioning = buffer.readInt();
@@ -196,7 +205,7 @@
verticalPositioning));
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Layout Operations", id(), name())
.description(
"Box layout implementation.\n\n"
@@ -224,7 +233,7 @@
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(buffer, mComponentId, mAnimationId, mHorizontalPositioning, mVerticalPositioning);
}
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/CanvasLayout.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/CanvasLayout.java
index f799767..12ff969 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/CanvasLayout.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/CanvasLayout.java
@@ -17,6 +17,8 @@
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.PaintContext;
@@ -44,6 +46,7 @@
this(parent, componentId, animationId, 0, 0, 0, 0);
}
+ @NonNull
@Override
public String toString() {
return "CANVAS ["
@@ -62,11 +65,13 @@
+ mVisibility;
}
+ @NonNull
@Override
protected String getSerializedName() {
return "CANVAS";
}
+ @NonNull
public static String name() {
return "CanvasLayout";
}
@@ -75,19 +80,19 @@
return Operations.LAYOUT_CANVAS;
}
- public static void apply(WireBuffer buffer, int componentId, int animationId) {
+ public static void apply(@NonNull WireBuffer buffer, int componentId, int animationId) {
buffer.start(Operations.LAYOUT_CANVAS);
buffer.writeInt(componentId);
buffer.writeInt(animationId);
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int componentId = buffer.readInt();
int animationId = buffer.readInt();
operations.add(new CanvasLayout(null, componentId, animationId));
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Layout Operations", id(), name())
.description("Canvas implementation. Encapsulate draw operations.\n\n")
.field(INT, "COMPONENT_ID", "unique id for this component")
@@ -98,7 +103,7 @@
}
@Override
- public void internalLayoutMeasure(PaintContext context, MeasurePass measure) {
+ public void internalLayoutMeasure(PaintContext context, @NonNull MeasurePass measure) {
ComponentMeasure selfMeasure = measure.get(this);
float selfWidth = selfMeasure.getW() - mPaddingLeft - mPaddingRight;
float selfHeight = selfMeasure.getH() - mPaddingTop - mPaddingBottom;
@@ -112,7 +117,7 @@
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(buffer, mComponentId, mAnimationId);
}
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/ColumnLayout.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/ColumnLayout.java
index 402b784..52bf4c5 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/ColumnLayout.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/ColumnLayout.java
@@ -18,6 +18,8 @@
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.FLOAT;
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.PaintContext;
@@ -87,6 +89,7 @@
spacedBy);
}
+ @NonNull
@Override
public String toString() {
return "COLUMN ["
@@ -105,14 +108,24 @@
+ mVisibility;
}
+ @NonNull
@Override
protected String getSerializedName() {
return "COLUMN";
}
@Override
+ public boolean isInVerticalFill() {
+ return super.isInVerticalFill() || childrenHaveVerticalWeights();
+ }
+
+ @Override
public void computeWrapSize(
- PaintContext context, float maxWidth, float maxHeight, MeasurePass measure, Size size) {
+ PaintContext context,
+ float maxWidth,
+ float maxHeight,
+ @NonNull MeasurePass measure,
+ @NonNull Size size) {
DebugLog.s(() -> "COMPUTE WRAP SIZE in " + this + " (" + mComponentId + ")");
int visibleChildrens = 0;
for (Component c : mChildrenComponents) {
@@ -137,7 +150,7 @@
float maxWidth,
float minHeight,
float maxHeight,
- MeasurePass measure) {
+ @NonNull MeasurePass measure) {
DebugLog.s(() -> "COMPUTE SIZE in " + this + " (" + mComponentId + ")");
float mh = maxHeight;
for (Component child : mChildrenComponents) {
@@ -151,7 +164,7 @@
}
@Override
- public void internalLayoutMeasure(PaintContext context, MeasurePass measure) {
+ public void internalLayoutMeasure(PaintContext context, @NonNull MeasurePass measure) {
ComponentMeasure selfMeasure = measure.get(this);
DebugLog.s(
() ->
@@ -302,6 +315,7 @@
DebugLog.e();
}
+ @NonNull
public static String name() {
return "ColumnLayout";
}
@@ -311,7 +325,7 @@
}
public static void apply(
- WireBuffer buffer,
+ @NonNull WireBuffer buffer,
int componentId,
int animationId,
int horizontalPositioning,
@@ -325,7 +339,7 @@
buffer.writeFloat(spacedBy);
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int componentId = buffer.readInt();
int animationId = buffer.readInt();
int horizontalPositioning = buffer.readInt();
@@ -341,7 +355,7 @@
spacedBy));
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Layout Operations", id(), name())
.description(
"Column layout implementation, positioning components one"
@@ -374,7 +388,7 @@
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(
buffer,
mComponentId,
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/LayoutManager.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/LayoutManager.java
index 308ed64..0c4d24a 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/LayoutManager.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/LayoutManager.java
@@ -15,6 +15,8 @@
*/
package com.android.internal.widget.remotecompose.core.operations.layout.managers;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.PaintContext;
import com.android.internal.widget.remotecompose.core.RemoteContext;
import com.android.internal.widget.remotecompose.core.operations.layout.Component;
@@ -27,7 +29,7 @@
/** Base class for layout managers -- resizable components. */
public abstract class LayoutManager extends LayoutComponent implements Measurable {
- Size mCachedWrapSize = new Size(0f, 0f);
+ @NonNull Size mCachedWrapSize = new Size(0f, 0f);
public LayoutManager(
Component parent,
@@ -62,6 +64,38 @@
// nothing here
}
+ protected boolean childrenHaveHorizontalWeights() {
+ for (Component c : mChildrenComponents) {
+ if (c instanceof LayoutManager) {
+ LayoutManager m = (LayoutManager) c;
+ if (m.getWidthModifier() != null && m.getWidthModifier().hasWeight()) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ protected boolean childrenHaveVerticalWeights() {
+ for (Component c : mChildrenComponents) {
+ if (c instanceof LayoutManager) {
+ LayoutManager m = (LayoutManager) c;
+ if (m.getHeightModifier() != null && m.getHeightModifier().hasWeight()) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public boolean isInHorizontalFill() {
+ return mWidthModifier.isFill();
+ }
+
+ public boolean isInVerticalFill() {
+ return mHeightModifier.isFill();
+ }
+
/** Base implementation of the measure resolution */
@Override
public void measure(
@@ -70,7 +104,7 @@
float maxWidth,
float minHeight,
float maxHeight,
- MeasurePass measure) {
+ @NonNull MeasurePass measure) {
boolean hasWrap = true;
float measuredWidth =
Math.min(maxWidth, computeModifierDefinedWidth() - mMarginLeft - mMarginRight);
@@ -87,7 +121,7 @@
} else {
hasWrap = false;
}
- if (mWidthModifier.isFill()) {
+ if (isInHorizontalFill()) {
measuredWidth = insetMaxWidth;
} else if (mWidthModifier.hasWeight()) {
measuredWidth = Math.max(measuredWidth, computeModifierDefinedWidth());
@@ -95,7 +129,7 @@
measuredWidth = Math.max(measuredWidth, minWidth);
measuredWidth = Math.min(measuredWidth, insetMaxWidth);
}
- if (mHeightModifier.isFill()) {
+ if (isInVerticalFill()) {
measuredHeight = insetMaxHeight;
} else if (mHeightModifier.hasWeight()) {
measuredHeight = Math.max(measuredHeight, computeModifierDefinedHeight());
@@ -136,7 +170,7 @@
/** basic layout of internal components */
@Override
- public void layout(RemoteContext context, MeasurePass measure) {
+ public void layout(@NonNull RemoteContext context, @NonNull MeasurePass measure) {
super.layout(context, measure);
ComponentMeasure self = measure.get(this);
@@ -153,7 +187,7 @@
* @param context
* @param measure
*/
- public void selfLayout(RemoteContext context, MeasurePass measure) {
+ public void selfLayout(@NonNull RemoteContext context, @NonNull MeasurePass measure) {
super.layout(context, measure);
ComponentMeasure self = measure.get(this);
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/RowLayout.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/RowLayout.java
index b29a05c..a366dc8 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/RowLayout.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/RowLayout.java
@@ -18,6 +18,8 @@
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.FLOAT;
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.PaintContext;
@@ -85,6 +87,7 @@
spacedBy);
}
+ @NonNull
@Override
public String toString() {
return "ROW ["
@@ -103,14 +106,24 @@
+ mVisibility;
}
+ @NonNull
@Override
protected String getSerializedName() {
return "ROW";
}
@Override
+ public boolean isInHorizontalFill() {
+ return super.isInHorizontalFill() || childrenHaveHorizontalWeights();
+ }
+
+ @Override
public void computeWrapSize(
- PaintContext context, float maxWidth, float maxHeight, MeasurePass measure, Size size) {
+ PaintContext context,
+ float maxWidth,
+ float maxHeight,
+ @NonNull MeasurePass measure,
+ @NonNull Size size) {
DebugLog.s(() -> "COMPUTE WRAP SIZE in " + this + " (" + mComponentId + ")");
// int visibleChildrens = 0;
for (Component c : mChildrenComponents) {
@@ -135,7 +148,7 @@
float maxWidth,
float minHeight,
float maxHeight,
- MeasurePass measure) {
+ @NonNull MeasurePass measure) {
DebugLog.s(() -> "COMPUTE SIZE in " + this + " (" + mComponentId + ")");
float mw = maxWidth;
for (Component child : mChildrenComponents) {
@@ -149,7 +162,7 @@
}
@Override
- public void internalLayoutMeasure(PaintContext context, MeasurePass measure) {
+ public void internalLayoutMeasure(PaintContext context, @NonNull MeasurePass measure) {
ComponentMeasure selfMeasure = measure.get(this);
DebugLog.s(
() ->
@@ -305,6 +318,7 @@
DebugLog.e();
}
+ @NonNull
public static String name() {
return "RowLayout";
}
@@ -314,7 +328,7 @@
}
public static void apply(
- WireBuffer buffer,
+ @NonNull WireBuffer buffer,
int componentId,
int animationId,
int horizontalPositioning,
@@ -328,7 +342,7 @@
buffer.writeFloat(spacedBy);
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int componentId = buffer.readInt();
int animationId = buffer.readInt();
int horizontalPositioning = buffer.readInt();
@@ -344,7 +358,7 @@
spacedBy));
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Layout Operations", id(), name())
.description(
"Row layout implementation, positioning components one"
@@ -377,7 +391,7 @@
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(
buffer,
mComponentId,
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/StateLayout.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/StateLayout.java
index b5c7281..e47ffde 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/StateLayout.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/StateLayout.java
@@ -15,6 +15,8 @@
*/
package com.android.internal.widget.remotecompose.core.operations.layout.managers;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.CoreDocument;
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
@@ -50,10 +52,10 @@
// This keep track of all the components associated with a given Id,
// (the key being the id), and the set of components corresponds to the set of states
// TODO: we should be able to optimize this
- public Map<Integer, Component[]> statePaintedComponents = new HashMap<>();
+ @NonNull public Map<Integer, Component[]> statePaintedComponents = new HashMap<>();
public int MAX_CACHE_ELEMENTS = 16;
- public int[] cacheListElementsId = new int[MAX_CACHE_ELEMENTS];
+ @NonNull public int[] cacheListElementsId = new int[MAX_CACHE_ELEMENTS];
public boolean inTransition = false;
@@ -168,7 +170,7 @@
}
@Override
- public void layout(RemoteContext context, MeasurePass measure) {
+ public void layout(@NonNull RemoteContext context, @NonNull MeasurePass measure) {
ComponentMeasure self = measure.get(this);
super.selfLayout(context, measure);
@@ -207,12 +209,12 @@
@Override
public void measure(
- PaintContext context,
+ @NonNull PaintContext context,
float minWidth,
float maxWidth,
float minHeight,
float maxHeight,
- MeasurePass measure) {
+ @NonNull MeasurePass measure) {
// The general approach for this widget is to do most of the work/setup in measure.
// layout and paint then simply use what's been setup in the measure phase.
@@ -364,19 +366,20 @@
}
@Override
- public void paint(PaintContext context) {
+ public void paint(@NonNull PaintContext context) {
if (mIndexId != 0) {
int newValue = context.getContext().mRemoteComposeState.getInteger(mIndexId);
if (newValue != currentLayoutIndex) {
previousLayoutIndex = currentLayoutIndex;
currentLayoutIndex = newValue;
inTransition = true;
- System.out.println("currentLayout index is $currentLayoutIndex");
+ // System.out.println("currentLayout index is $currentLayoutIndex");
// executeValueSetActions(getLayout(currentLayoutIndex));
invalidateMeasure();
}
}
- System.out.println("PAINTING LAYOUT STATELAYOUT, CURRENT INDEX " + currentLayoutIndex);
+ // System.out.println("PAINTING LAYOUT STATELAYOUT, CURRENT INDEX " +
+ // currentLayoutIndex);
// Make sure to mark any components that are not in either the current or previous layout
// as being GONE.
int index = 0;
@@ -529,6 +532,7 @@
// }
// }
+ @NonNull
@Override
public String toString() {
return "STATE_LAYOUT";
@@ -539,7 +543,7 @@
// }
public static void apply(
- WireBuffer buffer,
+ @NonNull WireBuffer buffer,
int componentId,
int animationId,
int horizontalPositioning,
@@ -553,7 +557,7 @@
buffer.writeInt(indexId);
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int componentId = buffer.readInt();
int animationId = buffer.readInt();
buffer.readInt(); // horizontalPositioning
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/TextLayout.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/TextLayout.java
index c1cabcd..8aa7712 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/TextLayout.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/TextLayout.java
@@ -18,6 +18,8 @@
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.FLOAT;
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.PaintContext;
@@ -44,22 +46,24 @@
private int mFontStyle = 0;
private float mFontWeight = 400f;
private int mFontFamilyId = -1;
+ private int mTextAlign = -1;
private int mType = -1;
private float mTextX;
private float mTextY;
+ private float mTextW;
private String mCachedString = "";
@Override
- public void registerListening(RemoteContext context) {
+ public void registerListening(@NonNull RemoteContext context) {
if (mTextId != -1) {
context.listensTo(mTextId, this);
}
}
@Override
- public void updateVariables(RemoteContext context) {
+ public void updateVariables(@NonNull RemoteContext context) {
mCachedString = context.getText(mTextId);
if (mType == -1) {
if (mFontFamilyId != -1) {
@@ -97,7 +101,8 @@
float fontSize,
int fontStyle,
float fontWeight,
- int fontFamilyId) {
+ int fontFamilyId,
+ int textAlign) {
super(parent, componentId, animationId, x, y, width, height);
mTextId = textId;
mColor = color;
@@ -105,6 +110,7 @@
mFontStyle = fontStyle;
mFontWeight = fontWeight;
mFontFamilyId = fontFamilyId;
+ mTextAlign = textAlign;
}
public TextLayout(
@@ -116,7 +122,8 @@
float fontSize,
int fontStyle,
float fontWeight,
- int fontFamilyId) {
+ int fontFamilyId,
+ int textAlign) {
this(
parent,
componentId,
@@ -130,13 +137,14 @@
fontSize,
fontStyle,
fontWeight,
- fontFamilyId);
+ fontFamilyId,
+ textAlign);
}
- public PaintBundle mPaint = new PaintBundle();
+ @NonNull public PaintBundle mPaint = new PaintBundle();
@Override
- public void paintingComponent(PaintContext context) {
+ public void paintingComponent(@NonNull PaintContext context) {
context.save();
context.translate(mX, mY);
mComponentModifiers.paint(context);
@@ -176,6 +184,7 @@
context.restore();
}
+ @NonNull
@Override
public String toString() {
return "TEXT_LAYOUT ["
@@ -194,13 +203,14 @@
+ mVisibility;
}
+ @NonNull
@Override
protected String getSerializedName() {
return "TEXT_LAYOUT";
}
@Override
- public void serializeToString(int indent, StringSerializer serializer) {
+ public void serializeToString(int indent, @NonNull StringSerializer serializer) {
serializer.append(
indent,
getSerializedName()
@@ -228,7 +238,11 @@
@Override
public void computeWrapSize(
- PaintContext context, float maxWidth, float maxHeight, MeasurePass measure, Size size) {
+ @NonNull PaintContext context,
+ float maxWidth,
+ float maxHeight,
+ MeasurePass measure,
+ @NonNull Size size) {
context.savePaint();
mPaint.reset();
mPaint.setTextSize(mFontSize);
@@ -244,8 +258,10 @@
mTextX = -bounds[0];
size.setHeight(h);
mTextY = -bounds[1];
+ mTextW = w;
}
+ @NonNull
public static String name() {
return "TextLayout";
}
@@ -255,7 +271,7 @@
}
public static void apply(
- WireBuffer buffer,
+ @NonNull WireBuffer buffer,
int componentId,
int animationId,
int textId,
@@ -263,7 +279,8 @@
float fontSize,
int fontStyle,
float fontWeight,
- int fontFamilyId) {
+ int fontFamilyId,
+ int textAlign) {
buffer.start(id());
buffer.writeInt(componentId);
buffer.writeInt(animationId);
@@ -273,9 +290,10 @@
buffer.writeInt(fontStyle);
buffer.writeFloat(fontWeight);
buffer.writeInt(fontFamilyId);
+ buffer.writeInt(textAlign);
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int componentId = buffer.readInt();
int animationId = buffer.readInt();
int textId = buffer.readInt();
@@ -284,6 +302,7 @@
int fontStyle = buffer.readInt();
float fontWeight = buffer.readFloat();
int fontFamilyId = buffer.readInt();
+ int textAlign = buffer.readInt();
operations.add(
new TextLayout(
null,
@@ -294,10 +313,11 @@
fontSize,
fontStyle,
fontWeight,
- fontFamilyId));
+ fontFamilyId,
+ textAlign));
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Layout Operations", id(), name())
.description("Text layout implementation.\n\n")
.field(INT, "COMPONENT_ID", "unique id for this component")
@@ -313,7 +333,7 @@
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(
buffer,
mComponentId,
@@ -323,6 +343,7 @@
mFontSize,
mFontStyle,
mFontWeight,
- mFontFamilyId);
+ mFontFamilyId,
+ mTextAlign);
}
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/measure/ComponentMeasure.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/measure/ComponentMeasure.java
index 285425f..426e023 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/measure/ComponentMeasure.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/measure/ComponentMeasure.java
@@ -15,6 +15,8 @@
*/
package com.android.internal.widget.remotecompose.core.operations.layout.measure;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.operations.layout.Component;
/** Encapsulate the result of a measure pass for a component */
@@ -80,7 +82,7 @@
this(id, x, y, w, h, Component.Visibility.VISIBLE);
}
- public ComponentMeasure(Component component) {
+ public ComponentMeasure(@NonNull Component component) {
this(
component.getComponentId(),
component.getX(),
@@ -90,7 +92,7 @@
component.mVisibility);
}
- public void copyFrom(ComponentMeasure m) {
+ public void copyFrom(@NonNull ComponentMeasure m) {
mX = m.mX;
mY = m.mY;
mW = m.mW;
@@ -98,7 +100,7 @@
mVisibility = m.mVisibility;
}
- public boolean same(ComponentMeasure m) {
+ public boolean same(@NonNull ComponentMeasure m) {
return mX == m.mX && mY == m.mY && mW == m.mW && mH == m.mH && mVisibility == m.mVisibility;
}
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/measure/MeasurePass.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/measure/MeasurePass.java
index 8d01fea..112ab1b 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/measure/MeasurePass.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/measure/MeasurePass.java
@@ -15,6 +15,8 @@
*/
package com.android.internal.widget.remotecompose.core.operations.layout.measure;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.operations.layout.Component;
import java.util.HashMap;
@@ -24,13 +26,13 @@
* array vs the current hashmap
*/
public class MeasurePass {
- HashMap<Integer, ComponentMeasure> mList = new HashMap<>();
+ @NonNull HashMap<Integer, ComponentMeasure> mList = new HashMap<>();
public void clear() {
mList.clear();
}
- public void add(ComponentMeasure measure) throws Exception {
+ public void add(@NonNull ComponentMeasure measure) throws Exception {
if (measure.mId == -1) {
throw new Exception("Component has no id!");
}
@@ -41,7 +43,7 @@
return mList.containsKey(id);
}
- public ComponentMeasure get(Component c) {
+ public ComponentMeasure get(@NonNull Component c) {
if (!mList.containsKey(c.getComponentId())) {
ComponentMeasure measure =
new ComponentMeasure(
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/BackgroundModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/BackgroundModifierOperation.java
index 64e40f7..76a97ca 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/BackgroundModifierOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/BackgroundModifierOperation.java
@@ -17,6 +17,8 @@
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.FLOAT;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.PaintContext;
@@ -42,7 +44,7 @@
float mA;
int mShapeType = ShapeType.RECTANGLE;
- public PaintBundle mPaint = new PaintBundle();
+ @NonNull public PaintBundle mPaint = new PaintBundle();
public BackgroundModifierOperation(
float x,
@@ -66,12 +68,12 @@
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(buffer, mX, mY, mWidth, mHeight, mR, mG, mB, mA, mShapeType);
}
@Override
- public void serializeToString(int indent, StringSerializer serializer) {
+ public void serializeToString(int indent, @NonNull StringSerializer serializer) {
serializer.append(
indent,
"BACKGROUND = ["
@@ -101,11 +103,13 @@
this.mHeight = height;
}
+ @NonNull
@Override
public String toString() {
return "BackgroundModifierOperation(" + mWidth + " x " + mHeight + ")";
}
+ @NonNull
public static String name() {
return CLASS_NAME;
}
@@ -115,7 +119,7 @@
}
public static void apply(
- WireBuffer buffer,
+ @NonNull WireBuffer buffer,
float x,
float y,
float width,
@@ -138,7 +142,7 @@
buffer.writeInt(shapeType);
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
float x = buffer.readFloat();
float y = buffer.readFloat();
float width = buffer.readFloat();
@@ -153,7 +157,7 @@
}
@Override
- public void paint(PaintContext context) {
+ public void paint(@NonNull PaintContext context) {
context.savePaint();
mPaint.reset();
mPaint.setStyle(PaintBundle.STYLE_FILL);
@@ -167,7 +171,7 @@
context.restorePaint();
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Modifier Operations", OP_CODE, CLASS_NAME)
.description("define the Background Modifier")
.field(FLOAT, "x", "")
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/BorderModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/BorderModifierOperation.java
index 92c0a73..d48a9c7 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/BorderModifierOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/BorderModifierOperation.java
@@ -17,6 +17,8 @@
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.FLOAT;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.PaintContext;
@@ -45,7 +47,7 @@
float mA;
int mShapeType = ShapeType.RECTANGLE;
- public PaintBundle paint = new PaintBundle();
+ @NonNull public PaintBundle paint = new PaintBundle();
public BorderModifierOperation(
float x,
@@ -73,7 +75,7 @@
}
@Override
- public void serializeToString(int indent, StringSerializer serializer) {
+ public void serializeToString(int indent, @NonNull StringSerializer serializer) {
serializer.append(
indent,
"BORDER = ["
@@ -105,7 +107,7 @@
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(
buffer,
mX,
@@ -127,6 +129,7 @@
this.mHeight = height;
}
+ @NonNull
@Override
public String toString() {
return "BorderModifierOperation("
@@ -152,6 +155,7 @@
+ ")";
}
+ @NonNull
public static String name() {
return CLASS_NAME;
}
@@ -161,7 +165,7 @@
}
public static void apply(
- WireBuffer buffer,
+ @NonNull WireBuffer buffer,
float x,
float y,
float width,
@@ -188,7 +192,7 @@
buffer.writeInt(shapeType);
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
float x = buffer.readFloat();
float y = buffer.readFloat();
float width = buffer.readFloat();
@@ -206,7 +210,7 @@
}
@Override
- public void paint(PaintContext context) {
+ public void paint(@NonNull PaintContext context) {
context.savePaint();
paint.reset();
paint.setColor(mR, mG, mB, mA);
@@ -225,7 +229,7 @@
context.restorePaint();
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Modifier Operations", OP_CODE, CLASS_NAME)
.description("define the Border Modifier")
.field(FLOAT, "x", "")
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ClipRectModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ClipRectModifierOperation.java
index 0d8aeaa..78b51c3 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ClipRectModifierOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ClipRectModifierOperation.java
@@ -15,14 +15,14 @@
*/
package com.android.internal.widget.remotecompose.core.operations.layout.modifiers;
-import com.android.internal.widget.remotecompose.core.CoreDocument;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.PaintContext;
import com.android.internal.widget.remotecompose.core.RemoteContext;
import com.android.internal.widget.remotecompose.core.WireBuffer;
import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder;
-import com.android.internal.widget.remotecompose.core.operations.layout.Component;
import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer;
import java.util.List;
@@ -35,7 +35,7 @@
float mHeight;
@Override
- public void paint(PaintContext context) {
+ public void paint(@NonNull PaintContext context) {
context.clipRect(0f, 0f, mWidth, mHeight);
}
@@ -46,21 +46,16 @@
}
@Override
- public void onClick(
- RemoteContext context, CoreDocument document, Component component, float x, float y) {
- // nothing
- }
-
- @Override
- public void serializeToString(int indent, StringSerializer serializer) {
+ public void serializeToString(int indent, @NonNull StringSerializer serializer) {
serializer.append(indent, "CLIP_RECT = [" + mWidth + ", " + mHeight + "]");
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(buffer);
}
+ @NonNull
public static String name() {
return CLASS_NAME;
}
@@ -69,15 +64,15 @@
return OP_CODE;
}
- public static void apply(WireBuffer buffer) {
+ public static void apply(@NonNull WireBuffer buffer) {
buffer.start(OP_CODE);
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(WireBuffer buffer, @NonNull List<Operation> operations) {
operations.add(new ClipRectModifierOperation());
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Canvas Operations", OP_CODE, CLASS_NAME)
.description("Draw the specified round-rect");
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ComponentModifiers.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ComponentModifiers.java
index 95786a8..011d7ed 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ComponentModifiers.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ComponentModifiers.java
@@ -15,6 +15,8 @@
*/
package com.android.internal.widget.remotecompose.core.operations.layout.modifiers;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.CoreDocument;
import com.android.internal.widget.remotecompose.core.PaintContext;
import com.android.internal.widget.remotecompose.core.PaintOperation;
@@ -22,29 +24,34 @@
import com.android.internal.widget.remotecompose.core.WireBuffer;
import com.android.internal.widget.remotecompose.core.operations.MatrixRestore;
import com.android.internal.widget.remotecompose.core.operations.MatrixSave;
+import com.android.internal.widget.remotecompose.core.operations.layout.ClickHandler;
import com.android.internal.widget.remotecompose.core.operations.layout.ClickModifierOperation;
import com.android.internal.widget.remotecompose.core.operations.layout.Component;
import com.android.internal.widget.remotecompose.core.operations.layout.DecoratorComponent;
+import com.android.internal.widget.remotecompose.core.operations.layout.TouchHandler;
import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer;
import java.util.ArrayList;
/** Maintain a list of modifiers */
-public class ComponentModifiers extends PaintOperation implements DecoratorComponent {
- ArrayList<ModifierOperation> mList = new ArrayList<>();
+public class ComponentModifiers extends PaintOperation
+ implements DecoratorComponent, ClickHandler, TouchHandler {
+ @NonNull ArrayList<ModifierOperation> mList = new ArrayList<>();
+ @NonNull
public ArrayList<ModifierOperation> getList() {
return mList;
}
@Override
- public void apply(RemoteContext context) {
+ public void apply(@NonNull RemoteContext context) {
super.apply(context);
for (ModifierOperation op : mList) {
op.apply(context);
}
}
+ @NonNull
@Override
public String toString() {
String str = "ComponentModifiers \n";
@@ -59,7 +66,7 @@
// nothing
}
- public void serializeToString(int indent, StringSerializer serializer) {
+ public void serializeToString(int indent, @NonNull StringSerializer serializer) {
serializer.append(indent, "MODIFIERS");
for (ModifierOperation m : mList) {
m.serializeToString(indent + 1, serializer);
@@ -75,7 +82,7 @@
}
@Override
- public void paint(PaintContext context) {
+ public void paint(@NonNull PaintContext context) {
float tx = 0f;
float ty = 0f;
for (ModifierOperation op : mList) {
@@ -127,8 +134,38 @@
public void onClick(
RemoteContext context, CoreDocument document, Component component, float x, float y) {
for (ModifierOperation op : mList) {
- if (op instanceof DecoratorComponent) {
- ((DecoratorComponent) op).onClick(context, document, component, x, y);
+ if (op instanceof ClickHandler) {
+ ((ClickHandler) op).onClick(context, document, component, x, y);
+ }
+ }
+ }
+
+ @Override
+ public void onTouchDown(
+ RemoteContext context, CoreDocument document, Component component, float x, float y) {
+ for (ModifierOperation op : mList) {
+ if (op instanceof TouchHandler) {
+ ((TouchHandler) op).onTouchDown(context, document, component, x, y);
+ }
+ }
+ }
+
+ @Override
+ public void onTouchUp(
+ RemoteContext context, CoreDocument document, Component component, float x, float y) {
+ for (ModifierOperation op : mList) {
+ if (op instanceof TouchHandler) {
+ ((TouchHandler) op).onTouchUp(context, document, component, x, y);
+ }
+ }
+ }
+
+ @Override
+ public void onTouchCancel(
+ RemoteContext context, CoreDocument document, Component component, float x, float y) {
+ for (ModifierOperation op : mList) {
+ if (op instanceof TouchHandler) {
+ ((TouchHandler) op).onTouchCancel(context, document, component, x, y);
}
}
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ComponentVisibilityOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ComponentVisibilityOperation.java
index 312d016..26e737b3 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ComponentVisibilityOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ComponentVisibilityOperation.java
@@ -17,7 +17,9 @@
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT;
-import com.android.internal.widget.remotecompose.core.CoreDocument;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.RemoteContext;
@@ -37,49 +39,52 @@
private static final int OP_CODE = Operations.MODIFIER_VISIBILITY;
int mVisibilityId;
- Component.Visibility mVisibility = Component.Visibility.VISIBLE;
+ @NonNull Component.Visibility mVisibility = Component.Visibility.VISIBLE;
private LayoutComponent mParent;
public ComponentVisibilityOperation(int id) {
mVisibilityId = id;
}
+ @NonNull
@Override
public String toString() {
return "ComponentVisibilityOperation(" + mVisibilityId + ")";
}
+ @NonNull
public String serializedName() {
return "COMPONENT_VISIBILITY";
}
@Override
- public void serializeToString(int indent, StringSerializer serializer) {
+ public void serializeToString(int indent, @NonNull StringSerializer serializer) {
serializer.append(indent, serializedName() + " = " + mVisibilityId);
}
@Override
public void apply(RemoteContext context) {}
+ @NonNull
@Override
- public String deepToString(String indent) {
+ public String deepToString(@Nullable String indent) {
return (indent != null ? indent : "") + toString();
}
@Override
public void write(WireBuffer buffer) {}
- public static void apply(WireBuffer buffer, int valueId) {
+ public static void apply(@NonNull WireBuffer buffer, int valueId) {
buffer.start(OP_CODE);
buffer.writeInt(valueId);
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int valueId = buffer.readInt();
operations.add(new ComponentVisibilityOperation(valueId));
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Layout Operations", OP_CODE, "ComponentVisibility")
.description(
"This operation allows setting a component"
@@ -88,12 +93,12 @@
}
@Override
- public void registerListening(RemoteContext context) {
+ public void registerListening(@NonNull RemoteContext context) {
context.listensTo(mVisibilityId, this);
}
@Override
- public void updateVariables(RemoteContext context) {
+ public void updateVariables(@NonNull RemoteContext context) {
int visibility = context.getInteger(mVisibilityId);
if (visibility == Component.Visibility.VISIBLE.ordinal()) {
mVisibility = Component.Visibility.VISIBLE;
@@ -115,8 +120,4 @@
@Override
public void layout(RemoteContext context, float width, float height) {}
-
- @Override
- public void onClick(
- RemoteContext context, CoreDocument document, Component component, float x, float y) {}
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/DecoratorModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/DecoratorModifierOperation.java
index 41e18cb..b4c4108 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/DecoratorModifierOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/DecoratorModifierOperation.java
@@ -15,10 +15,7 @@
*/
package com.android.internal.widget.remotecompose.core.operations.layout.modifiers;
-import com.android.internal.widget.remotecompose.core.CoreDocument;
import com.android.internal.widget.remotecompose.core.PaintOperation;
-import com.android.internal.widget.remotecompose.core.RemoteContext;
-import com.android.internal.widget.remotecompose.core.operations.layout.Component;
import com.android.internal.widget.remotecompose.core.operations.layout.DecoratorComponent;
/**
@@ -26,11 +23,4 @@
* output (background, border...)
*/
public abstract class DecoratorModifierOperation extends PaintOperation
- implements ModifierOperation, DecoratorComponent {
-
- @Override
- public void onClick(
- RemoteContext context, CoreDocument document, Component component, float x, float y) {
- // nothing
- }
-}
+ implements ModifierOperation, DecoratorComponent {}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/DimensionModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/DimensionModifierOperation.java
index 408bebc..3c2d85c 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/DimensionModifierOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/DimensionModifierOperation.java
@@ -15,6 +15,9 @@
*/
package com.android.internal.widget.remotecompose.core.operations.layout.modifiers;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
import com.android.internal.widget.remotecompose.core.RemoteContext;
import com.android.internal.widget.remotecompose.core.VariableSupport;
import com.android.internal.widget.remotecompose.core.operations.Utils;
@@ -29,8 +32,10 @@
WRAP,
WEIGHT,
INTRINSIC_MIN,
- INTRINSIC_MAX;
+ INTRINSIC_MAX,
+ EXACT_DP;
+ @NonNull
static Type fromInt(int value) {
switch (value) {
case 0:
@@ -45,6 +50,8 @@
return INTRINSIC_MIN;
case 5:
return INTRINSIC_MAX;
+ case 6:
+ return EXACT_DP;
}
return EXACT;
}
@@ -68,19 +75,32 @@
}
@Override
- public void updateVariables(RemoteContext context) {
+ public void updateVariables(@NonNull RemoteContext context) {
if (mType == Type.EXACT) {
mOutValue = Float.isNaN(mValue) ? context.getFloat(Utils.idFromNan(mValue)) : mValue;
}
+ if (mType == Type.EXACT_DP) {
+ float pre = mOutValue;
+ mOutValue = Float.isNaN(mValue) ? context.getFloat(Utils.idFromNan(mValue)) : mValue;
+ mOutValue *= context.getDensity();
+ if (pre != mOutValue) {
+ context.getDocument().getRootLayoutComponent().invalidateMeasure();
+ }
+ }
}
@Override
- public void registerListening(RemoteContext context) {
+ public void registerListening(@NonNull RemoteContext context) {
if (mType == Type.EXACT) {
if (Float.isNaN(mValue)) {
context.listensTo(Utils.idFromNan(mValue), this);
}
}
+ if (mType == Type.EXACT_DP) {
+ if (Float.isNaN(mValue)) {
+ context.listensTo(Utils.idFromNan(mValue), this);
+ }
+ }
}
public boolean hasWeight() {
@@ -107,25 +127,31 @@
mOutValue = mValue = value;
}
+ @NonNull
public String serializedName() {
return "DIMENSION";
}
@Override
- public void serializeToString(int indent, StringSerializer serializer) {
+ public void serializeToString(int indent, @NonNull StringSerializer serializer) {
if (mType == Type.EXACT) {
serializer.append(indent, serializedName() + " = " + mValue);
}
+ if (mType == Type.EXACT_DP) {
+ serializer.append(indent, serializedName() + " = " + mValue + " dp");
+ }
}
@Override
public void apply(RemoteContext context) {}
+ @NonNull
@Override
- public String deepToString(String indent) {
+ public String deepToString(@Nullable String indent) {
return (indent != null ? indent : "") + toString();
}
+ @NonNull
@Override
public String toString() {
return "DimensionModifierOperation(" + mValue + ")";
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/GraphicsLayerModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/GraphicsLayerModifierOperation.java
new file mode 100644
index 0000000..2b30382
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/GraphicsLayerModifierOperation.java
@@ -0,0 +1,302 @@
+/*
+ * Copyright (C) 2024 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.internal.widget.remotecompose.core.operations.layout.modifiers;
+
+import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.FLOAT;
+import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT;
+
+import com.android.internal.widget.remotecompose.core.Operation;
+import com.android.internal.widget.remotecompose.core.Operations;
+import com.android.internal.widget.remotecompose.core.PaintContext;
+import com.android.internal.widget.remotecompose.core.RemoteContext;
+import com.android.internal.widget.remotecompose.core.WireBuffer;
+import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder;
+import com.android.internal.widget.remotecompose.core.operations.layout.AnimatableValue;
+import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer;
+
+import java.util.List;
+
+/**
+ * Represents a padding modifier. Padding modifiers can be chained and will impact following
+ * modifiers.
+ */
+public class GraphicsLayerModifierOperation extends DecoratorModifierOperation {
+ private static final int OP_CODE = Operations.MODIFIER_GRAPHICS_LAYER;
+ public static final String CLASS_NAME = "GraphicsLayerModifierOperation";
+
+ AnimatableValue mScaleX;
+ AnimatableValue mScaleY;
+ AnimatableValue mRotationX;
+ AnimatableValue mRotationY;
+ AnimatableValue mRotationZ;
+ AnimatableValue mTransformOriginX;
+ AnimatableValue mTransformOriginY;
+ AnimatableValue mShadowElevation;
+ AnimatableValue mAlpha;
+ AnimatableValue mCameraDistance;
+ int mBlendMode;
+ int mSpotShadowColorId;
+ int mAmbientShadowColorId;
+ int mColorFilterId;
+ int mRenderEffectId;
+
+ public GraphicsLayerModifierOperation(
+ float scaleX,
+ float scaleY,
+ float rotationX,
+ float rotationY,
+ float rotationZ,
+ float shadowElevation,
+ float transformOriginX,
+ float transformOriginY,
+ float alpha,
+ float cameraDistance,
+ int blendMode,
+ int spotShadowColorId,
+ int ambientShadowColorId,
+ int colorFilterId,
+ int renderEffectId) {
+ mScaleX = new AnimatableValue(scaleX);
+ mScaleY = new AnimatableValue(scaleY);
+ mRotationX = new AnimatableValue(rotationX);
+ mRotationY = new AnimatableValue(rotationY);
+ mRotationZ = new AnimatableValue(rotationZ);
+ mShadowElevation = new AnimatableValue(shadowElevation);
+ mTransformOriginX = new AnimatableValue(transformOriginX);
+ mTransformOriginY = new AnimatableValue(transformOriginY);
+ mAlpha = new AnimatableValue(alpha);
+ mCameraDistance = new AnimatableValue(cameraDistance);
+ mBlendMode = blendMode;
+ mSpotShadowColorId = spotShadowColorId;
+ mAmbientShadowColorId = ambientShadowColorId;
+ mColorFilterId = colorFilterId;
+ mRenderEffectId = renderEffectId;
+ }
+
+ public float getScaleX() {
+ return mScaleX.getValue();
+ }
+
+ public float getScaleY() {
+ return mScaleY.getValue();
+ }
+
+ public float getRotationX() {
+ return mRotationX.getValue();
+ }
+
+ public float getRotationY() {
+ return mRotationY.getValue();
+ }
+
+ public float getRotationZ() {
+ return mRotationZ.getValue();
+ }
+
+ public float getShadowElevation() {
+ return mShadowElevation.getValue();
+ }
+
+ public float getTransformOriginX() {
+ return mTransformOriginX.getValue();
+ }
+
+ public float getTransformOriginY() {
+ return mTransformOriginY.getValue();
+ }
+
+ public float getAlpha() {
+ return mAlpha.getValue();
+ }
+
+ public float getCameraDistance() {
+ return mCameraDistance.getValue();
+ }
+
+ // TODO: add implementation for blendmode
+ public int getBlendModeId() {
+ return mBlendMode;
+ }
+
+ // TODO: add implementation for shadow
+ public int getSpotShadowColorId() {
+ return mSpotShadowColorId;
+ }
+
+ public int getAmbientShadowColorId() {
+ return mAmbientShadowColorId;
+ }
+
+ // TODO: add implementation for color filters
+ public int getColorFilterId() {
+ return mColorFilterId;
+ }
+
+ public int getRenderEffectId() {
+ return mRenderEffectId;
+ }
+
+ @Override
+ public void write(WireBuffer buffer) {
+ apply(
+ buffer,
+ mScaleX.getValue(),
+ mScaleY.getValue(),
+ mRotationX.getValue(),
+ mRotationY.getValue(),
+ mRotationZ.getValue(),
+ mShadowElevation.getValue(),
+ mTransformOriginX.getValue(),
+ mTransformOriginY.getValue(),
+ mAlpha.getValue(),
+ mCameraDistance.getValue(),
+ mBlendMode,
+ mSpotShadowColorId,
+ mAmbientShadowColorId,
+ mColorFilterId,
+ mRenderEffectId);
+ }
+
+ @Override
+ public void serializeToString(int indent, StringSerializer serializer) {
+ serializer.append(indent, "GRAPHICS_LAYER = [" + mScaleX + ", " + mScaleY + "]");
+ }
+
+ @Override
+ public String deepToString(String indent) {
+ return (indent != null ? indent : "") + toString();
+ }
+
+ @Override
+ public void paint(PaintContext context) {
+ mScaleX.evaluate(context);
+ mScaleY.evaluate(context);
+ mRotationX.evaluate(context);
+ mRotationY.evaluate(context);
+ mRotationZ.evaluate(context);
+ mTransformOriginX.evaluate(context);
+ mTransformOriginY.evaluate(context);
+ mShadowElevation.evaluate(context);
+ mAlpha.evaluate(context);
+ mCameraDistance.evaluate(context);
+ }
+
+ @Override
+ public String toString() {
+ return "GraphicsLayerModifierOperation(" + mScaleX + ", " + mScaleY + ")";
+ }
+
+ public static String name() {
+ return CLASS_NAME;
+ }
+
+ public static int id() {
+ return OP_CODE;
+ }
+
+ public static void apply(
+ WireBuffer buffer,
+ float scaleX,
+ float scaleY,
+ float rotationX,
+ float rotationY,
+ float rotationZ,
+ float shadowElevation,
+ float transformOriginX,
+ float transformOriginY,
+ float alpha,
+ float cameraDistance,
+ int blendMode,
+ int spotShadowColorId,
+ int ambientShadowColorId,
+ int colorFilterId,
+ int renderEffectId) {
+ buffer.start(OP_CODE);
+ buffer.writeFloat(scaleX);
+ buffer.writeFloat(scaleY);
+ buffer.writeFloat(rotationX);
+ buffer.writeFloat(rotationY);
+ buffer.writeFloat(rotationZ);
+ buffer.writeFloat(shadowElevation);
+ buffer.writeFloat(transformOriginX);
+ buffer.writeFloat(transformOriginY);
+ buffer.writeFloat(alpha);
+ buffer.writeFloat(cameraDistance);
+ buffer.writeInt(blendMode);
+ buffer.writeInt(spotShadowColorId);
+ buffer.writeInt(ambientShadowColorId);
+ buffer.writeInt(colorFilterId);
+ buffer.writeInt(renderEffectId);
+ }
+
+ public static void read(WireBuffer buffer, List<Operation> operations) {
+ float scaleX = buffer.readFloat();
+ float scaleY = buffer.readFloat();
+ float rotationX = buffer.readFloat();
+ float rotationY = buffer.readFloat();
+ float rotationZ = buffer.readFloat();
+ float shadowElevation = buffer.readFloat();
+ float transformOriginX = buffer.readFloat();
+ float transformOriginY = buffer.readFloat();
+ float alpha = buffer.readFloat();
+ float cameraDistance = buffer.readFloat();
+ int blendMode = buffer.readInt();
+ int spotShadowColorId = buffer.readInt();
+ int ambientShadowColorId = buffer.readInt();
+ int colorFilterId = buffer.readInt();
+ int renderEffectId = buffer.readInt();
+ operations.add(
+ new GraphicsLayerModifierOperation(
+ scaleX,
+ scaleY,
+ rotationX,
+ rotationY,
+ rotationZ,
+ shadowElevation,
+ transformOriginX,
+ transformOriginY,
+ alpha,
+ cameraDistance,
+ blendMode,
+ spotShadowColorId,
+ ambientShadowColorId,
+ colorFilterId,
+ renderEffectId));
+ }
+
+ public static void documentation(DocumentationBuilder doc) {
+ doc.operation("Modifier Operations", OP_CODE, CLASS_NAME)
+ .description("define the GraphicsLayer Modifier")
+ .field(FLOAT, "scaleX", "")
+ .field(FLOAT, "scaleY", "")
+ .field(FLOAT, "rotationX", "")
+ .field(FLOAT, "rotationY", "")
+ .field(FLOAT, "rotationZ", "")
+ .field(FLOAT, "shadowElevation", "")
+ .field(FLOAT, "transformOriginX", "")
+ .field(FLOAT, "transformOriginY", "")
+ .field(FLOAT, "alpha", "")
+ .field(FLOAT, "cameraDistance", "")
+ .field(INT, "blendMode", "")
+ .field(INT, "spotShadowColorId", "")
+ .field(INT, "ambientShadowColorId", "")
+ .field(INT, "colorFilterId", "")
+ .field(INT, "renderEffectId", "");
+ }
+
+ @Override
+ public void layout(RemoteContext context, float width, float height) {}
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HeightModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HeightModifierOperation.java
index d3613f8..97c76c0 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HeightModifierOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HeightModifierOperation.java
@@ -18,6 +18,8 @@
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.FLOAT;
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.WireBuffer;
@@ -30,6 +32,7 @@
private static final int OP_CODE = Operations.MODIFIER_HEIGHT;
public static final String CLASS_NAME = "HeightModifierOperation";
+ @NonNull
public static String name() {
return CLASS_NAME;
}
@@ -38,13 +41,13 @@
return OP_CODE;
}
- public static void apply(WireBuffer buffer, int type, float value) {
+ public static void apply(@NonNull WireBuffer buffer, int type, float value) {
buffer.start(OP_CODE);
buffer.writeInt(type);
buffer.writeFloat(value);
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
Type type = Type.fromInt(buffer.readInt());
float value = buffer.readFloat();
Operation op = new HeightModifierOperation(type, value);
@@ -52,7 +55,7 @@
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(buffer, mType.ordinal(), mValue);
}
@@ -68,17 +71,19 @@
super(value);
}
+ @NonNull
@Override
public String toString() {
- return "Height(" + mValue + ")";
+ return "Height(" + mType + ", " + mValue + ")";
}
+ @NonNull
@Override
public String serializedName() {
return "HEIGHT";
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Modifier Operations", OP_CODE, CLASS_NAME)
.description("define the animation")
.field(INT, "type", "")
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HostActionOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HostActionOperation.java
index ac42470a..836321f 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HostActionOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HostActionOperation.java
@@ -17,6 +17,9 @@
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
import com.android.internal.widget.remotecompose.core.CoreDocument;
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
@@ -39,6 +42,7 @@
mActionId = id;
}
+ @NonNull
@Override
public String toString() {
return "HostActionOperation(" + mActionId + ")";
@@ -48,20 +52,22 @@
return mActionId;
}
+ @NonNull
public String serializedName() {
return "HOST_ACTION";
}
@Override
- public void serializeToString(int indent, StringSerializer serializer) {
+ public void serializeToString(int indent, @NonNull StringSerializer serializer) {
serializer.append(indent, serializedName() + " = " + mActionId);
}
@Override
public void apply(RemoteContext context) {}
+ @NonNull
@Override
- public String deepToString(String indent) {
+ public String deepToString(@Nullable String indent) {
return (indent != null ? indent : "") + toString();
}
@@ -70,21 +76,25 @@
@Override
public void runAction(
- RemoteContext context, CoreDocument document, Component component, float x, float y) {
+ @NonNull RemoteContext context,
+ CoreDocument document,
+ Component component,
+ float x,
+ float y) {
context.runAction(mActionId, "");
}
- public static void apply(WireBuffer buffer, int actionId) {
+ public static void apply(@NonNull WireBuffer buffer, int actionId) {
buffer.start(OP_CODE);
buffer.writeInt(actionId);
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int actionId = buffer.readInt();
operations.add(new HostActionOperation(actionId));
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Layout Operations", OP_CODE, "HostAction")
.description("Host action. This operation represents a host action")
.field(INT, "ACTION_ID", "Host Action ID");
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HostNamedActionOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HostNamedActionOperation.java
index b674a58..e97e897 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HostNamedActionOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HostNamedActionOperation.java
@@ -17,6 +17,9 @@
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
import com.android.internal.widget.remotecompose.core.CoreDocument;
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
@@ -33,31 +36,47 @@
public class HostNamedActionOperation implements ActionOperation {
private static final int OP_CODE = Operations.HOST_NAMED_ACTION;
- int mTextId = -1;
+ public static final int FLOAT_TYPE = 0;
+ public static final int INT_TYPE = 1;
+ public static final int STRING_TYPE = 2;
+ public static final int NONE_TYPE = -1;
- public HostNamedActionOperation(int id) {
+ int mTextId = -1;
+ int mType = NONE_TYPE;
+ int mValueId = -1;
+
+ public HostNamedActionOperation(int id, int type, int valueId) {
mTextId = id;
+ mType = type;
+ mValueId = valueId;
}
+ @NonNull
@Override
public String toString() {
- return "HostNamedActionOperation(" + mTextId + ")";
+ return "HostNamedActionOperation(" + mTextId + " : " + mValueId + ")";
}
+ @NonNull
public String serializedName() {
return "HOST_NAMED_ACTION";
}
@Override
- public void serializeToString(int indent, StringSerializer serializer) {
- serializer.append(indent, serializedName() + " = " + mTextId);
+ public void serializeToString(int indent, @NonNull StringSerializer serializer) {
+ if (mValueId != -1) {
+ serializer.append(indent, serializedName() + " = " + mTextId + " : " + mValueId);
+ } else {
+ serializer.append(indent, serializedName() + " = " + mTextId);
+ }
}
@Override
public void apply(RemoteContext context) {}
+ @NonNull
@Override
- public String deepToString(String indent) {
+ public String deepToString(@Nullable String indent) {
return (indent != null ? indent : "") + toString();
}
@@ -66,23 +85,42 @@
@Override
public void runAction(
- RemoteContext context, CoreDocument document, Component component, float x, float y) {
- context.runNamedAction(mTextId);
+ @NonNull RemoteContext context,
+ CoreDocument document,
+ Component component,
+ float x,
+ float y) {
+ Object value = null;
+ if (mValueId != -1) {
+ if (mType == INT_TYPE) {
+ value = context.mRemoteComposeState.getInteger(mValueId);
+ } else if (mType == STRING_TYPE) {
+ value = context.mRemoteComposeState.getFromId(mValueId);
+ } else if (mType == FLOAT_TYPE) {
+ value = context.mRemoteComposeState.getFloat(mValueId);
+ }
+ }
+ context.runNamedAction(mTextId, value);
}
- public static void apply(WireBuffer buffer, int textId) {
+ public static void apply(@NonNull WireBuffer buffer, int textId, int type, int valueId) {
buffer.start(OP_CODE);
buffer.writeInt(textId);
+ buffer.writeInt(type);
+ buffer.writeInt(valueId);
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int textId = buffer.readInt();
- operations.add(new HostNamedActionOperation(textId));
+ int type = buffer.readInt();
+ int valueId = buffer.readInt();
+ operations.add(new HostNamedActionOperation(textId, type, valueId));
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Layout Operations", OP_CODE, "HostNamedAction")
.description("Host Named action. This operation represents a host action")
- .field(INT, "TEXT_ID", "Named Host Action Text ID");
+ .field(INT, "TEXT_ID", "Named Host Action Text ID")
+ .field(INT, "VALUE_ID", "Named Host Action Value ID");
}
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/OffsetModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/OffsetModifierOperation.java
new file mode 100644
index 0000000..65fe345
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/OffsetModifierOperation.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2024 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.internal.widget.remotecompose.core.operations.layout.modifiers;
+
+import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.FLOAT;
+
+import com.android.internal.widget.remotecompose.core.Operation;
+import com.android.internal.widget.remotecompose.core.Operations;
+import com.android.internal.widget.remotecompose.core.PaintContext;
+import com.android.internal.widget.remotecompose.core.RemoteContext;
+import com.android.internal.widget.remotecompose.core.WireBuffer;
+import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder;
+import com.android.internal.widget.remotecompose.core.operations.Utils;
+import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer;
+
+import java.util.List;
+
+/** Represents an offset modifier. */
+public class OffsetModifierOperation extends DecoratorModifierOperation {
+ private static final int OP_CODE = Operations.MODIFIER_OFFSET;
+ public static final String CLASS_NAME = "OffsetModifierOperation";
+
+ float mX;
+ float mY;
+
+ public OffsetModifierOperation(float x, float y) {
+ this.mX = x;
+ this.mY = y;
+ }
+
+ public float getX() {
+ return mX;
+ }
+
+ public float getY() {
+ return mY;
+ }
+
+ public void setX(float x) {
+ this.mX = x;
+ }
+
+ public void setY(float y) {
+ this.mY = y;
+ }
+
+ @Override
+ public void write(WireBuffer buffer) {
+ apply(buffer, mX, mY);
+ }
+
+ // @Override
+ public void serializeToString(int indent, StringSerializer serializer) {
+ serializer.append(indent, "OFFSET = [" + mX + ", " + mY + "]");
+ }
+
+ @Override
+ public String deepToString(String indent) {
+ return (indent != null ? indent : "") + toString();
+ }
+
+ @Override
+ public void paint(PaintContext context) {
+ float x = context.getContext().mRemoteComposeState.getFloat(Utils.idFromNan(mX));
+ float y = context.getContext().mRemoteComposeState.getFloat(Utils.idFromNan(mY));
+ float density = context.getContext().getDensity();
+ x *= density;
+ y *= density;
+ context.translate(x, y);
+ }
+
+ @Override
+ public String toString() {
+ return "OffsetModifierOperation(" + mX + ", " + mY + ")";
+ }
+
+ public static String name() {
+ return CLASS_NAME;
+ }
+
+ public static int id() {
+ return OP_CODE;
+ }
+
+ public static void apply(WireBuffer buffer, float x, float y) {
+ buffer.start(OP_CODE);
+ buffer.writeFloat(x);
+ buffer.writeFloat(y);
+ }
+
+ public static void read(WireBuffer buffer, List<Operation> operations) {
+ float x = buffer.readFloat();
+ float y = buffer.readFloat();
+ operations.add(new OffsetModifierOperation(x, y));
+ }
+
+ public static void documentation(DocumentationBuilder doc) {
+ doc.operation("Modifier Operations", OP_CODE, CLASS_NAME)
+ .description("define the Offset Modifier")
+ .field(FLOAT, "x", "")
+ .field(FLOAT, "y", "");
+ }
+
+ @Override
+ public void layout(RemoteContext context, float width, float height) {}
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/PaddingModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/PaddingModifierOperation.java
index e0ec1a6..ed5522e 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/PaddingModifierOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/PaddingModifierOperation.java
@@ -17,6 +17,9 @@
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.FLOAT;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.RemoteContext;
@@ -78,12 +81,12 @@
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(buffer, mLeft, mTop, mRight, mBottom);
}
@Override
- public void serializeToString(int indent, StringSerializer serializer) {
+ public void serializeToString(int indent, @NonNull StringSerializer serializer) {
serializer.append(
indent, "PADDING = [" + mLeft + ", " + mTop + ", " + mRight + ", " + mBottom + "]");
}
@@ -91,11 +94,13 @@
@Override
public void apply(RemoteContext context) {}
+ @NonNull
@Override
- public String deepToString(String indent) {
+ public String deepToString(@Nullable String indent) {
return (indent != null ? indent : "") + toString();
}
+ @NonNull
@Override
public String toString() {
return "PaddingModifierOperation("
@@ -109,6 +114,7 @@
+ ")";
}
+ @NonNull
public static String name() {
return CLASS_NAME;
}
@@ -117,7 +123,8 @@
return Operations.MODIFIER_PADDING;
}
- public static void apply(WireBuffer buffer, float left, float top, float right, float bottom) {
+ public static void apply(
+ @NonNull WireBuffer buffer, float left, float top, float right, float bottom) {
buffer.start(Operations.MODIFIER_PADDING);
buffer.writeFloat(left);
buffer.writeFloat(top);
@@ -125,7 +132,7 @@
buffer.writeFloat(bottom);
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
float left = buffer.readFloat();
float top = buffer.readFloat();
float right = buffer.readFloat();
@@ -133,7 +140,7 @@
operations.add(new PaddingModifierOperation(left, top, right, bottom));
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Modifier Operations", OP_CODE, CLASS_NAME)
.description("define the Padding Modifier")
.field(FLOAT, "left", "")
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/RoundedClipRectModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/RoundedClipRectModifierOperation.java
index dc95fe7..6218dd5 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/RoundedClipRectModifierOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/RoundedClipRectModifierOperation.java
@@ -17,7 +17,8 @@
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.FLOAT;
-import com.android.internal.widget.remotecompose.core.CoreDocument;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.PaintContext;
@@ -25,7 +26,6 @@
import com.android.internal.widget.remotecompose.core.WireBuffer;
import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder;
import com.android.internal.widget.remotecompose.core.operations.DrawBase4;
-import com.android.internal.widget.remotecompose.core.operations.layout.Component;
import com.android.internal.widget.remotecompose.core.operations.layout.DecoratorComponent;
import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer;
@@ -37,7 +37,7 @@
public static final int OP_CODE = Operations.MODIFIER_ROUNDED_CLIP_RECT;
public static final String CLASS_NAME = "RoundedClipRectModifierOperation";
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
Maker m = RoundedClipRectModifierOperation::new;
read(m, buffer, operations);
}
@@ -46,16 +46,17 @@
return OP_CODE;
}
+ @NonNull
public static String name() {
return CLASS_NAME;
}
@Override
- protected void write(WireBuffer buffer, float v1, float v2, float v3, float v4) {
+ protected void write(@NonNull WireBuffer buffer, float v1, float v2, float v3, float v4) {
apply(buffer, v1, v2, v3, v4);
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Modifier Operations", id(), "RoundedClipRectModifierOperation")
.description("clip with rectangle")
.field(
@@ -90,7 +91,7 @@
}
@Override
- public void paint(PaintContext context) {
+ public void paint(@NonNull PaintContext context) {
context.roundedClipRect(mWidth, mHeight, mX1, mY1, mX2, mY2);
}
@@ -101,13 +102,7 @@
}
@Override
- public void onClick(
- RemoteContext context, CoreDocument document, Component component, float x, float y) {
- // nothing
- }
-
- @Override
- public void serializeToString(int indent, StringSerializer serializer) {
+ public void serializeToString(int indent, @NonNull StringSerializer serializer) {
serializer.append(
indent,
"ROUNDED_CLIP_RECT = ["
@@ -135,7 +130,11 @@
* @param bottomEnd bottomEnd radius
*/
public static void apply(
- WireBuffer buffer, float topStart, float topEnd, float bottomStart, float bottomEnd) {
+ @NonNull WireBuffer buffer,
+ float topStart,
+ float topEnd,
+ float bottomStart,
+ float bottomEnd) {
write(buffer, OP_CODE, topStart, topEnd, bottomStart, bottomEnd);
}
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueFloatChangeActionOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueFloatChangeActionOperation.java
new file mode 100644
index 0000000..29ec828
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueFloatChangeActionOperation.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2024 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.internal.widget.remotecompose.core.operations.layout.modifiers;
+
+import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.FLOAT;
+import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT;
+
+import com.android.internal.widget.remotecompose.core.CoreDocument;
+import com.android.internal.widget.remotecompose.core.Operation;
+import com.android.internal.widget.remotecompose.core.Operations;
+import com.android.internal.widget.remotecompose.core.RemoteContext;
+import com.android.internal.widget.remotecompose.core.WireBuffer;
+import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder;
+import com.android.internal.widget.remotecompose.core.operations.layout.ActionOperation;
+import com.android.internal.widget.remotecompose.core.operations.layout.Component;
+import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer;
+
+import java.util.List;
+
+/** Apply a value change on an float variable. */
+public class ValueFloatChangeActionOperation implements ActionOperation {
+ private static final int OP_CODE = Operations.VALUE_FLOAT_CHANGE_ACTION;
+
+ int mTargetValueId = -1;
+ float mValue = -1;
+
+ public ValueFloatChangeActionOperation(int id, float value) {
+ mTargetValueId = id;
+ mValue = value;
+ }
+
+ @Override
+ public String toString() {
+ return "ValueFloatChangeActionOperation(" + mTargetValueId + ")";
+ }
+
+ public String serializedName() {
+ return "VALUE_FLOAT_CHANGE";
+ }
+
+ @Override
+ public void serializeToString(int indent, StringSerializer serializer) {
+ serializer.append(indent, serializedName() + " = " + mTargetValueId + " -> " + mValue);
+ }
+
+ @Override
+ public void apply(RemoteContext context) {}
+
+ @Override
+ public String deepToString(String indent) {
+ return (indent != null ? indent : "") + toString();
+ }
+
+ @Override
+ public void write(WireBuffer buffer) {}
+
+ @Override
+ public void runAction(
+ RemoteContext context, CoreDocument document, Component component, float x, float y) {
+ System.out.println("OVERRIDE " + mTargetValueId + " TO " + mValue);
+ context.overrideFloat(mTargetValueId, mValue);
+ }
+
+ public static void apply(WireBuffer buffer, int valueId, float value) {
+ buffer.start(OP_CODE);
+ buffer.writeInt(valueId);
+ buffer.writeFloat(value);
+ }
+
+ public static void read(WireBuffer buffer, List<Operation> operations) {
+ int valueId = buffer.readInt();
+ float value = buffer.readFloat();
+ operations.add(new ValueFloatChangeActionOperation(valueId, value));
+ }
+
+ public static void documentation(DocumentationBuilder doc) {
+ doc.operation("Layout Operations", OP_CODE, "ValueFloatChangeActionOperation")
+ .description(
+ "ValueIntegerChange action. "
+ + " This operation represents a value change for the given id")
+ .field(INT, "TARGET_VALUE_ID", "Value ID")
+ .field(FLOAT, "VALUE", "float value to be assigned to the target");
+ }
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueIntegerChangeActionOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueIntegerChangeActionOperation.java
index 8876720..d7ce8ac 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueIntegerChangeActionOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueIntegerChangeActionOperation.java
@@ -17,6 +17,9 @@
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
import com.android.internal.widget.remotecompose.core.CoreDocument;
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
@@ -41,25 +44,28 @@
mValue = value;
}
+ @NonNull
@Override
public String toString() {
return "ValueChangeActionOperation(" + mTargetValueId + ")";
}
+ @NonNull
public String serializedName() {
return "VALUE_INTEGER_CHANGE";
}
@Override
- public void serializeToString(int indent, StringSerializer serializer) {
+ public void serializeToString(int indent, @NonNull StringSerializer serializer) {
serializer.append(indent, serializedName() + " = " + mTargetValueId + " -> " + mValue);
}
@Override
public void apply(RemoteContext context) {}
+ @NonNull
@Override
- public String deepToString(String indent) {
+ public String deepToString(@Nullable String indent) {
return (indent != null ? indent : "") + toString();
}
@@ -68,23 +74,27 @@
@Override
public void runAction(
- RemoteContext context, CoreDocument document, Component component, float x, float y) {
+ @NonNull RemoteContext context,
+ CoreDocument document,
+ Component component,
+ float x,
+ float y) {
context.overrideInteger(mTargetValueId, mValue);
}
- public static void apply(WireBuffer buffer, int valueId, int value) {
+ public static void apply(@NonNull WireBuffer buffer, int valueId, int value) {
buffer.start(OP_CODE);
buffer.writeInt(valueId);
buffer.writeInt(value);
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int valueId = buffer.readInt();
int value = buffer.readInt();
operations.add(new ValueIntegerChangeActionOperation(valueId, value));
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Layout Operations", OP_CODE, "ValueIntegerChangeActionOperation")
.description(
"ValueIntegerChange action. "
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueIntegerExpressionChangeActionOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueIntegerExpressionChangeActionOperation.java
index fb5e911..75d13e7 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueIntegerExpressionChangeActionOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueIntegerExpressionChangeActionOperation.java
@@ -17,6 +17,9 @@
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
import com.android.internal.widget.remotecompose.core.CoreDocument;
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
@@ -41,17 +44,19 @@
mValueExpressionId = value;
}
+ @NonNull
@Override
public String toString() {
return "ValueIntegerExpressionChangeActionOperation(" + mTargetValueId + ")";
}
+ @NonNull
public String serializedName() {
return "VALUE_INTEGER_EXPRESSION_CHANGE";
}
@Override
- public void serializeToString(int indent, StringSerializer serializer) {
+ public void serializeToString(int indent, @NonNull StringSerializer serializer) {
serializer.append(
indent, serializedName() + " = " + mTargetValueId + " -> " + mValueExpressionId);
}
@@ -59,8 +64,9 @@
@Override
public void apply(RemoteContext context) {}
+ @NonNull
@Override
- public String deepToString(String indent) {
+ public String deepToString(@Nullable String indent) {
return (indent != null ? indent : "") + toString();
}
@@ -69,23 +75,27 @@
@Override
public void runAction(
- RemoteContext context, CoreDocument document, Component component, float x, float y) {
+ @NonNull RemoteContext context,
+ @NonNull CoreDocument document,
+ Component component,
+ float x,
+ float y) {
document.evaluateIntExpression(mValueExpressionId, (int) mTargetValueId, context);
}
- public static void apply(WireBuffer buffer, long valueId, long value) {
+ public static void apply(@NonNull WireBuffer buffer, long valueId, long value) {
buffer.start(OP_CODE);
buffer.writeLong(valueId);
buffer.writeLong(value);
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
long valueId = buffer.readLong();
long value = buffer.readLong();
operations.add(new ValueIntegerExpressionChangeActionOperation(valueId, value));
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Layout Operations", OP_CODE, "ValueIntegerExpressionChangeActionOperation")
.description(
"ValueIntegerExpressionChange action. "
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueStringChangeActionOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueStringChangeActionOperation.java
index a64a492..26d7244 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueStringChangeActionOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueStringChangeActionOperation.java
@@ -17,6 +17,9 @@
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
import com.android.internal.widget.remotecompose.core.CoreDocument;
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
@@ -41,6 +44,7 @@
mValueId = value;
}
+ @NonNull
@Override
public String toString() {
return "ValueChangeActionOperation(" + mTargetValueId + ")";
@@ -50,20 +54,22 @@
return mTargetValueId;
}
+ @NonNull
public String serializedName() {
return "VALUE_CHANGE";
}
@Override
- public void serializeToString(int indent, StringSerializer serializer) {
+ public void serializeToString(int indent, @NonNull StringSerializer serializer) {
serializer.append(indent, serializedName() + " = " + mTargetValueId + " -> " + mValueId);
}
@Override
public void apply(RemoteContext context) {}
+ @NonNull
@Override
- public String deepToString(String indent) {
+ public String deepToString(@Nullable String indent) {
return (indent != null ? indent : "") + toString();
}
@@ -72,23 +78,27 @@
@Override
public void runAction(
- RemoteContext context, CoreDocument document, Component component, float x, float y) {
+ @NonNull RemoteContext context,
+ CoreDocument document,
+ Component component,
+ float x,
+ float y) {
context.overrideText(mTargetValueId, mValueId);
}
- public static void apply(WireBuffer buffer, int valueId, int value) {
+ public static void apply(@NonNull WireBuffer buffer, int valueId, int value) {
buffer.start(OP_CODE);
buffer.writeInt(valueId);
buffer.writeInt(value);
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int valueId = buffer.readInt();
int value = buffer.readInt();
operations.add(new ValueStringChangeActionOperation(valueId, value));
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Layout Operations", OP_CODE, "ValueStringChangeActionOperation")
.description(
"ValueStrin gChange action. "
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/WidthModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/WidthModifierOperation.java
index 62403b3..e2f899c 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/WidthModifierOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/WidthModifierOperation.java
@@ -18,6 +18,8 @@
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.FLOAT;
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.WireBuffer;
@@ -30,6 +32,7 @@
private static final int OP_CODE = Operations.MODIFIER_WIDTH;
public static final String CLASS_NAME = "WidthModifierOperation";
+ @NonNull
public static String name() {
return CLASS_NAME;
}
@@ -38,13 +41,13 @@
return OP_CODE;
}
- public static void apply(WireBuffer buffer, int type, float value) {
+ public static void apply(@NonNull WireBuffer buffer, int type, float value) {
buffer.start(OP_CODE);
buffer.writeInt(type);
buffer.writeFloat(value);
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
Type type = Type.fromInt(buffer.readInt());
float value = buffer.readFloat();
Operation op = new WidthModifierOperation(type, value);
@@ -56,7 +59,7 @@
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(buffer, mType.ordinal(), mValue);
}
@@ -68,17 +71,19 @@
super(value);
}
+ @NonNull
@Override
public String toString() {
- return "Width(" + mValue + ")";
+ return "Width(" + mType + ", " + mValue + ")";
}
+ @NonNull
@Override
public String serializedName() {
return "WIDTH";
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Modifier Operations", OP_CODE, CLASS_NAME)
.description("define the animation")
.field(INT, "type", "")
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ZIndexModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ZIndexModifierOperation.java
new file mode 100644
index 0000000..aa20e03
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ZIndexModifierOperation.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2024 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.internal.widget.remotecompose.core.operations.layout.modifiers;
+
+import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.FLOAT;
+
+import com.android.internal.widget.remotecompose.core.Operation;
+import com.android.internal.widget.remotecompose.core.Operations;
+import com.android.internal.widget.remotecompose.core.PaintContext;
+import com.android.internal.widget.remotecompose.core.RemoteContext;
+import com.android.internal.widget.remotecompose.core.WireBuffer;
+import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder;
+import com.android.internal.widget.remotecompose.core.operations.Utils;
+import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer;
+
+import java.util.List;
+
+/** Represents a ZIndex modifier, allowing to change the z-index of a component. */
+public class ZIndexModifierOperation extends DecoratorModifierOperation {
+ private static final int OP_CODE = Operations.MODIFIER_ZINDEX;
+ public static final String CLASS_NAME = "ZIndexModifierOperation";
+ float mValue;
+ float mCurrentValue;
+
+ public ZIndexModifierOperation(float value) {
+ this.mValue = value;
+ }
+
+ public float getValue() {
+ return mCurrentValue;
+ }
+
+ public void setmValue(float value) {
+ this.mValue = value;
+ }
+
+ @Override
+ public void write(WireBuffer buffer) {
+ apply(buffer, mValue);
+ }
+
+ // @Override
+ public void serializeToString(int indent, StringSerializer serializer) {
+ serializer.append(indent, "ZINDEX = [" + mValue + "]");
+ }
+
+ @Override
+ public String deepToString(String indent) {
+ return (indent != null ? indent : "") + toString();
+ }
+
+ @Override
+ public void paint(PaintContext context) {
+ mCurrentValue = mValue;
+ if (Utils.isVariable(mValue)) {
+ mCurrentValue =
+ context.getContext().mRemoteComposeState.getFloat(Utils.idFromNan(mValue));
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "ZIndexModifierOperation(" + mValue + ")";
+ }
+
+ public static String name() {
+ return CLASS_NAME;
+ }
+
+ public static int id() {
+ return OP_CODE;
+ }
+
+ public static void apply(WireBuffer buffer, float value) {
+ buffer.start(OP_CODE);
+ buffer.writeFloat(value);
+ }
+
+ public static void read(WireBuffer buffer, List<Operation> operations) {
+ float value = buffer.readFloat();
+ operations.add(new ZIndexModifierOperation(value));
+ }
+
+ public static void documentation(DocumentationBuilder doc) {
+ doc.operation("Modifier Operations", OP_CODE, CLASS_NAME)
+ .description("define the Z-Index Modifier")
+ .field(FLOAT, "value", "");
+ }
+
+ @Override
+ public void layout(RemoteContext context, float width, float height) {}
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/utils/DebugLog.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/utils/DebugLog.java
index 4849b12..d8e49b0 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/utils/DebugLog.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/utils/DebugLog.java
@@ -15,6 +15,9 @@
*/
package com.android.internal.widget.remotecompose.core.operations.layout.utils;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
import java.util.ArrayList;
/** Internal utility debug class */
@@ -23,12 +26,12 @@
public static final boolean DEBUG_LAYOUT_ON = false;
public static class Node {
- public Node parent;
+ @Nullable public Node parent;
public String name;
public String endString;
- public ArrayList<Node> list = new ArrayList<>();
+ @NonNull public ArrayList<Node> list = new ArrayList<>();
- public Node(Node parent, String name) {
+ public Node(@Nullable Node parent, String name) {
this.parent = parent;
this.name = name;
this.endString = name + " DONE";
@@ -48,21 +51,21 @@
}
}
- public static Node node = new Node(null, "Root");
- public static Node currentNode = node;
+ @NonNull public static Node node = new Node(null, "Root");
+ @NonNull public static Node currentNode = node;
public static void clear() {
node = new Node(null, "Root");
currentNode = node;
}
- public static void s(StringValueSupplier valueSupplier) {
+ public static void s(@NonNull StringValueSupplier valueSupplier) {
if (DEBUG_LAYOUT_ON) {
currentNode = new Node(currentNode, valueSupplier.getString());
}
}
- public static void log(StringValueSupplier valueSupplier) {
+ public static void log(@NonNull StringValueSupplier valueSupplier) {
if (DEBUG_LAYOUT_ON) {
new LogNode(currentNode, valueSupplier.getString());
}
@@ -78,7 +81,7 @@
}
}
- public static void e(StringValueSupplier valueSupplier) {
+ public static void e(@NonNull StringValueSupplier valueSupplier) {
if (DEBUG_LAYOUT_ON) {
currentNode.endString = valueSupplier.getString();
if (currentNode.parent != null) {
@@ -89,7 +92,7 @@
}
}
- public static void printNode(int indent, Node node, StringBuilder builder) {
+ public static void printNode(int indent, @NonNull Node node, @NonNull StringBuilder builder) {
if (DEBUG_LAYOUT_ON) {
StringBuilder indentationBuilder = new StringBuilder();
for (int i = 0; i < indent; i++) {
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/paint/Painter.java b/core/java/com/android/internal/widget/remotecompose/core/operations/paint/Painter.java
index 9a3cd54..a808cf0 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/paint/Painter.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/paint/Painter.java
@@ -15,6 +15,8 @@
*/
package com.android.internal.widget.remotecompose.core.operations.paint;
+import android.annotation.NonNull;
+
/** Provides a Builder pattern for a PaintBundle */
class Painter {
PaintBundle mPaint;
@@ -24,16 +26,19 @@
return mPaint;
}
+ @NonNull
public Painter setAntiAlias(boolean aa) {
mPaint.setAntiAlias(aa);
return this;
}
+ @NonNull
public Painter setColor(int color) {
mPaint.setColor(color);
return this;
}
+ @NonNull
public Painter setColorId(int colorId) {
mPaint.setColorId(colorId);
return this;
@@ -44,6 +49,7 @@
*
* @param join set the paint's Join, used whenever the paint's style is Stroke or StrokeAndFill.
*/
+ @NonNull
public Painter setStrokeJoin(int join) {
mPaint.setStrokeJoin(join);
return this;
@@ -56,6 +62,7 @@
* @param width set the paint's stroke width, used whenever the paint's style is Stroke or
* StrokeAndFill.
*/
+ @NonNull
public Painter setStrokeWidth(float width) {
mPaint.setStrokeWidth(width);
return this;
@@ -67,6 +74,7 @@
*
* @param style The new style to set in the paint
*/
+ @NonNull
public Painter setStyle(int style) {
mPaint.setStyle(style);
return this;
@@ -78,6 +86,7 @@
* @param cap set the paint's line cap style, used whenever the paint's style is Stroke or
* StrokeAndFill.
*/
+ @NonNull
public Painter setStrokeCap(int cap) {
mPaint.setStrokeCap(cap);
return this;
@@ -90,6 +99,7 @@
* @param miter set the miter limit on the paint, used whenever the paint's style is Stroke or
* StrokeAndFill.
*/
+ @NonNull
public Painter setStrokeMiter(float miter) {
mPaint.setStrokeMiter(miter);
return this;
@@ -101,6 +111,7 @@
*
* @param alpha set the alpha component [0..1.0] of the paint's color.
*/
+ @NonNull
public Painter setAlpha(float alpha) {
mPaint.setAlpha((alpha > 2) ? alpha / 255f : alpha);
return this;
@@ -112,6 +123,7 @@
* @param color The ARGB source color used with the specified Porter-Duff mode
* @param mode The porter-duff mode that is applied
*/
+ @NonNull
public Painter setPorterDuffColorFilter(int color, int mode) {
mPaint.setColorFilter(color, mode);
return this;
@@ -130,6 +142,7 @@
* line.
* @param tileMode The Shader tiling mode
*/
+ @NonNull
public Painter setLinearGradient(
float startX,
float startY,
@@ -155,6 +168,7 @@
* circle.
* @param tileMode The Shader tiling mode
*/
+ @NonNull
public Painter setRadialGradient(
float centerX,
float centerY,
@@ -178,6 +192,7 @@
* may produce unexpected results. If positions is NULL, then the colors are automatically
* spaced evenly.
*/
+ @NonNull
public Painter setSweepGradient(float centerX, float centerY, int[] colors, float[] positions) {
mPaint.setSweepGradient(colors, 0, positions, centerX, centerY);
return this;
@@ -188,6 +203,7 @@
*
* @param size set the paint's text size in pixel units.
*/
+ @NonNull
public Painter setTextSize(float size) {
mPaint.setTextSize(size);
return this;
@@ -215,16 +231,19 @@
* @param weight The desired weight to be drawn.
* @param italic {@code true} if italic style is desired to be drawn. Otherwise, {@code false}
*/
+ @NonNull
public Painter setTypeface(int fontType, int weight, boolean italic) {
mPaint.setTextStyle(fontType, weight, italic);
return this;
}
+ @NonNull
public Painter setFilterBitmap(boolean filter) {
mPaint.setFilterBitmap(filter);
return this;
}
+ @NonNull
public Painter setShader(int id) {
mPaint.setShader(id);
return this;
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/AnimatedFloatExpression.java b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/AnimatedFloatExpression.java
index 1d673c4..b25f4cd 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/AnimatedFloatExpression.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/AnimatedFloatExpression.java
@@ -15,11 +15,12 @@
*/
package com.android.internal.widget.remotecompose.core.operations.utilities;
-/**
- * high performance floating point expression evaluator used in animation
- */
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+/** high performance floating point expression evaluator used in animation */
public class AnimatedFloatExpression {
- static IntMap<String> sNames = new IntMap<>();
+ @NonNull static IntMap<String> sNames = new IntMap<>();
public static final int OFFSET = 0x310_000;
public static final float ADD = asNan(OFFSET + 1);
public static final float SUB = asNan(OFFSET + 2);
@@ -74,7 +75,7 @@
private static final float FP_TO_DEG = 0.017453292f; // 180/PI
float[] mStack;
- float[] mLocalStack = new float[128];
+ @NonNull float[] mLocalStack = new float[128];
float[] mVar;
CollectionsAccess mCollectionsAccess;
@@ -201,7 +202,7 @@
* @param var
* @return
*/
- public float eval(float[] exp, int len, float... var) {
+ public float eval(@NonNull float[] exp, int len, float... var) {
System.arraycopy(exp, 0, mLocalStack, 0, len);
mStack = mLocalStack;
mVar = var;
@@ -224,7 +225,7 @@
* @param var
* @return
*/
- public float evalDB(float[] exp, float... var) {
+ public float evalDB(@NonNull float[] exp, float... var) {
mStack = exp;
mVar = var;
int sp = -1;
@@ -240,195 +241,281 @@
return mStack[sp];
}
- Op[] mOps = {
+ @NonNull Op[] mOps;
+
+ {
+ Op mADD =
+ (sp) -> { // ADD
+ mStack[sp - 1] = mStack[sp - 1] + mStack[sp];
+ return sp - 1;
+ };
+ Op mSUB =
+ (sp) -> { // SUB
+ mStack[sp - 1] = mStack[sp - 1] - mStack[sp];
+ return sp - 1;
+ };
+ Op mMUL =
+ (sp) -> { // MUL
+ mStack[sp - 1] = mStack[sp - 1] * mStack[sp];
+ return sp - 1;
+ };
+ Op mDIV =
+ (sp) -> { // DIV
+ mStack[sp - 1] = mStack[sp - 1] / mStack[sp];
+ return sp - 1;
+ };
+ Op mMOD =
+ (sp) -> { // MOD
+ mStack[sp - 1] = mStack[sp - 1] % mStack[sp];
+ return sp - 1;
+ };
+ Op mMIN =
+ (sp) -> { // MIN
+ mStack[sp - 1] = (float) Math.min(mStack[sp - 1], mStack[sp]);
+ return sp - 1;
+ };
+ Op mMAX =
+ (sp) -> { // MAX
+ mStack[sp - 1] = (float) Math.max(mStack[sp - 1], mStack[sp]);
+ return sp - 1;
+ };
+ Op mPOW =
+ (sp) -> { // POW
+ mStack[sp - 1] = (float) Math.pow(mStack[sp - 1], mStack[sp]);
+ return sp - 1;
+ };
+ Op mSQRT =
+ (sp) -> { // SQRT
+ mStack[sp] = (float) Math.sqrt(mStack[sp]);
+ return sp;
+ };
+ Op mABS =
+ (sp) -> { // ABS
+ mStack[sp] = (float) Math.abs(mStack[sp]);
+ return sp;
+ };
+ Op mSIGN =
+ (sp) -> { // SIGN
+ mStack[sp] = (float) Math.signum(mStack[sp]);
+ return sp;
+ };
+ Op mCOPY_SIGN =
+ (sp) -> { // copySign
+ mStack[sp - 1] = (float) Math.copySign(mStack[sp - 1], mStack[sp]);
+ return sp - 1;
+ };
+ Op mEXP =
+ (sp) -> { // EXP
+ mStack[sp] = (float) Math.exp(mStack[sp]);
+ return sp;
+ };
+ Op mFLOOR =
+ (sp) -> { // FLOOR
+ mStack[sp] = (float) Math.floor(mStack[sp]);
+ return sp;
+ };
+ Op mLOG =
+ (sp) -> { // LOG
+ mStack[sp] = (float) Math.log10(mStack[sp]);
+ return sp;
+ };
+ Op mLN =
+ (sp) -> { // LN
+ mStack[sp] = (float) Math.log(mStack[sp]);
+ return sp;
+ };
+ Op mROUND =
+ (sp) -> { // ROUND
+ mStack[sp] = (float) Math.round(mStack[sp]);
+ return sp;
+ };
+ Op mSIN =
+ (sp) -> { // SIN
+ mStack[sp] = (float) Math.sin(mStack[sp]);
+ return sp;
+ };
+ Op mCOS =
+ (sp) -> { // COS
+ mStack[sp] = (float) Math.cos(mStack[sp]);
+ return sp;
+ };
+ Op mTAN =
+ (sp) -> { // TAN
+ mStack[sp] = (float) Math.tan(mStack[sp]);
+ return sp;
+ };
+ Op mASIN =
+ (sp) -> { // ASIN
+ mStack[sp] = (float) Math.asin(mStack[sp]);
+ return sp;
+ };
+ Op mACOS =
+ (sp) -> { // ACOS
+ mStack[sp] = (float) Math.acos(mStack[sp]);
+ return sp;
+ };
+ Op mATAN =
+ (sp) -> { // ATAN
+ mStack[sp] = (float) Math.atan(mStack[sp]);
+ return sp;
+ };
+ Op mATAN2 =
+ (sp) -> { // ATAN2
+ mStack[sp - 1] = (float) Math.atan2(mStack[sp - 1], mStack[sp]);
+ return sp - 1;
+ };
+ Op mMAD =
+ (sp) -> { // MAD
+ mStack[sp - 2] = mStack[sp] + mStack[sp - 1] * mStack[sp - 2];
+ return sp - 2;
+ };
+ Op mTERNARY_CONDITIONAL =
+ (sp) -> { // TERNARY_CONDITIONAL
+ mStack[sp - 2] = (mStack[sp] > 0) ? mStack[sp - 1] : mStack[sp - 2];
+ return sp - 2;
+ };
+ Op mCLAMP =
+ (sp) -> { // CLAMP
+ mStack[sp - 2] = Math.min(Math.max(mStack[sp - 2], mStack[sp]), mStack[sp - 1]);
+ return sp - 2;
+ };
+ Op mCBRT =
+ (sp) -> { // CBRT
+ mStack[sp] = (float) Math.pow(mStack[sp], 1 / 3.);
+ return sp;
+ };
+ Op mDEG =
+ (sp) -> { // DEG
+ mStack[sp] = mStack[sp] * FP_TO_RAD;
+ return sp;
+ };
+ Op mRAD =
+ (sp) -> { // RAD
+ mStack[sp] = mStack[sp] * FP_TO_DEG;
+ return sp;
+ };
+ Op mCEIL =
+ (sp) -> { // CEIL
+ mStack[sp] = (float) Math.ceil(mStack[sp]);
+ return sp;
+ };
+ Op mA_DEREF =
+ (sp) -> { // A_DEREF
+ int id = fromNaN(mStack[sp]);
+ mStack[sp - 1] = mCollectionsAccess.getFloatValue(id, (int) mStack[sp - 1]);
+ return sp - 1;
+ };
+ Op mA_MAX =
+ (sp) -> { // A_MAX
+ int id = fromNaN(mStack[sp]);
+ float[] array = mCollectionsAccess.getFloats(id);
+ float max = array[0];
+ for (int i = 1; i < array.length; i++) {
+ max = Math.max(max, array[i]);
+ }
+ mStack[sp] = max;
+ return sp;
+ };
+ Op mA_MIN =
+ (sp) -> { // A_MIN
+ int id = fromNaN(mStack[sp]);
+ float[] array = mCollectionsAccess.getFloats(id);
+ float max = array[0];
+ for (int i = 1; i < array.length; i++) {
+ max = Math.max(max, array[i]);
+ }
+ mStack[sp] = max;
+ return sp;
+ };
+ Op mA_SUM =
+ (sp) -> { // A_SUM
+ int id = fromNaN(mStack[sp]);
+ float[] array = mCollectionsAccess.getFloats(id);
+ float sum = 0;
+ for (int i = 0; i < array.length; i++) {
+ sum += array[i];
+ }
+ mStack[sp] = sum;
+ return sp;
+ };
+ Op mA_AVG =
+ (sp) -> { // A_AVG
+ int id = fromNaN(mStack[sp]);
+ float[] array = mCollectionsAccess.getFloats(id);
+ float sum = 0;
+ for (int i = 0; i < array.length; i++) {
+ sum += array[i];
+ }
+ mStack[sp] = sum / array.length;
+ return sp;
+ };
+ Op mA_LEN =
+ (sp) -> { // A_LEN
+ int id = fromNaN(mStack[sp]);
+ mStack[sp] = mCollectionsAccess.getListLength(id);
+ return sp;
+ };
+ Op mFIRST_VAR =
+ (sp) -> { // FIRST_VAR
+ mStack[sp] = mVar[0];
+ return sp;
+ };
+ Op mSECOND_VAR =
+ (sp) -> { // SECOND_VAR
+ mStack[sp] = mVar[1];
+ return sp;
+ };
+ Op mTHIRD_VAR =
+ (sp) -> { // THIRD_VAR
+ mStack[sp] = mVar[2];
+ return sp;
+ };
+
+ Op[] ops = {
null,
- (sp) -> { // ADD
- mStack[sp - 1] = mStack[sp - 1] + mStack[sp];
- return sp - 1;
- },
- (sp) -> { // SUB
- mStack[sp - 1] = mStack[sp - 1] - mStack[sp];
- return sp - 1;
- },
- (sp) -> { // MUL
- mStack[sp - 1] = mStack[sp - 1] * mStack[sp];
- return sp - 1;
- },
- (sp) -> { // DIV
- mStack[sp - 1] = mStack[sp - 1] / mStack[sp];
- return sp - 1;
- },
- (sp) -> { // MOD
- mStack[sp - 1] = mStack[sp - 1] % mStack[sp];
- return sp - 1;
- },
- (sp) -> { // MIN
- mStack[sp - 1] = (float) Math.min(mStack[sp - 1], mStack[sp]);
- return sp - 1;
- },
- (sp) -> { // MAX
- mStack[sp - 1] = (float) Math.max(mStack[sp - 1], mStack[sp]);
- return sp - 1;
- },
- (sp) -> { // POW
- mStack[sp - 1] = (float) Math.pow(mStack[sp - 1], mStack[sp]);
- return sp - 1;
- },
- (sp) -> { // SQRT
- mStack[sp] = (float) Math.sqrt(mStack[sp]);
- return sp;
- },
- (sp) -> { // ABS
- mStack[sp] = (float) Math.abs(mStack[sp]);
- return sp;
- },
- (sp) -> { // SIGN
- mStack[sp] = (float) Math.signum(mStack[sp]);
- return sp;
- },
- (sp) -> { // copySign
- mStack[sp - 1] = (float) Math.copySign(mStack[sp - 1], mStack[sp]);
- return sp - 1;
- },
- (sp) -> { // EXP
- mStack[sp] = (float) Math.exp(mStack[sp]);
- return sp;
- },
- (sp) -> { // FLOOR
- mStack[sp] = (float) Math.floor(mStack[sp]);
- return sp;
- },
- (sp) -> { // LOG
- mStack[sp] = (float) Math.log10(mStack[sp]);
- return sp;
- },
- (sp) -> { // LN
- mStack[sp] = (float) Math.log(mStack[sp]);
- return sp;
- },
- (sp) -> { // ROUND
- mStack[sp] = (float) Math.round(mStack[sp]);
- return sp;
- },
- (sp) -> { // SIN
- mStack[sp] = (float) Math.sin(mStack[sp]);
- return sp;
- },
- (sp) -> { // COS
- mStack[sp] = (float) Math.cos(mStack[sp]);
- return sp;
- },
- (sp) -> { // TAN
- mStack[sp] = (float) Math.tan(mStack[sp]);
- return sp;
- },
- (sp) -> { // ASIN
- mStack[sp] = (float) Math.asin(mStack[sp]);
- return sp;
- },
- (sp) -> { // ACOS
- mStack[sp] = (float) Math.acos(mStack[sp]);
- return sp;
- },
- (sp) -> { // ATAN
- mStack[sp] = (float) Math.atan(mStack[sp]);
- return sp;
- },
- (sp) -> { // ATAN2
- mStack[sp - 1] = (float) Math.atan2(mStack[sp - 1], mStack[sp]);
- return sp - 1;
- },
- (sp) -> { // MAD
- mStack[sp - 2] = mStack[sp] + mStack[sp - 1] * mStack[sp - 2];
- return sp - 2;
- },
- (sp) -> { // Ternary conditional
- mStack[sp - 2] = (mStack[sp] > 0) ? mStack[sp - 1] : mStack[sp - 2];
- return sp - 2;
- },
- (sp) -> { // CLAMP(min,max, val)
- mStack[sp - 2] = Math.min(Math.max(mStack[sp - 2], mStack[sp]), mStack[sp - 1]);
- return sp - 2;
- },
- (sp) -> { // CBRT cuberoot
- mStack[sp] = (float) Math.pow(mStack[sp], 1 / 3.);
- return sp;
- },
- (sp) -> { // DEG
- mStack[sp] = mStack[sp] * FP_TO_RAD;
- return sp;
- },
- (sp) -> { // RAD
- mStack[sp] = mStack[sp] * FP_TO_DEG;
- return sp;
- },
- (sp) -> { // CEIL
- mStack[sp] = (float) Math.ceil(mStack[sp]);
- return sp;
- },
- (sp) -> { // A_DEREF
- int id = fromNaN(mStack[sp]);
- mStack[sp] = mCollectionsAccess.getFloatValue(id, (int) mStack[sp - 1]);
- return sp - 1;
- },
- (sp) -> { // A_MAX
- int id = fromNaN(mStack[sp]);
- float[] array = mCollectionsAccess.getFloats(id);
- float max = array[0];
- for (int i = 1; i < array.length; i++) {
- max = Math.max(max, array[i]);
- }
- mStack[sp] = max;
- return sp;
- },
- (sp) -> { // A_MIN
- int id = fromNaN(mStack[sp]);
- float[] array = mCollectionsAccess.getFloats(id);
- float max = array[0];
- for (int i = 1; i < array.length; i++) {
- max = Math.max(max, array[i]);
- }
- mStack[sp] = max;
- return sp;
- },
- (sp) -> { // A_SUM
- int id = fromNaN(mStack[sp]);
- float[] array = mCollectionsAccess.getFloats(id);
- float sum = 0;
- for (int i = 0; i < array.length; i++) {
- sum += array[i];
- }
- mStack[sp] = sum;
- return sp;
- },
- (sp) -> { // A_AVG
- int id = fromNaN(mStack[sp]);
- float[] array = mCollectionsAccess.getFloats(id);
- float sum = 0;
- for (int i = 0; i < array.length; i++) {
- sum += array[i];
- }
- mStack[sp] = sum / array.length;
- return sp;
- },
- (sp) -> { // A_LEN
- int id = fromNaN(mStack[sp]);
- mStack[sp] = mCollectionsAccess.getListLength(id);
- return sp;
- },
- (sp) -> { // first var =
- mStack[sp] = mVar[0];
- return sp;
- },
- (sp) -> { // second var y?
- mStack[sp] = mVar[1];
- return sp;
- },
- (sp) -> { // 3rd var z?
- mStack[sp] = mVar[2];
- return sp;
- },
- };
+ mADD,
+ mSUB,
+ mMUL,
+ mDIV,
+ mMOD,
+ mMIN,
+ mMAX,
+ mPOW,
+ mSQRT,
+ mABS,
+ mSIGN,
+ mCOPY_SIGN,
+ mEXP,
+ mFLOOR,
+ mLOG,
+ mLN,
+ mROUND,
+ mSIN,
+ mCOS,
+ mTAN,
+ mASIN,
+ mACOS,
+ mATAN,
+ mATAN2,
+ mMAD,
+ mTERNARY_CONDITIONAL,
+ mCLAMP,
+ mCBRT,
+ mDEG,
+ mRAD,
+ mCEIL,
+ mA_DEREF,
+ mA_MAX,
+ mA_MIN,
+ mA_SUM,
+ mA_AVG,
+ mA_LEN,
+ mFIRST_VAR,
+ mSECOND_VAR,
+ mTHIRD_VAR,
+ };
+ mOps = ops;
+ }
static {
int k = 0;
@@ -483,6 +570,7 @@
* @param f
* @return
*/
+ @Nullable
public static String toMathName(float f) {
int id = fromNaN(f) - OFFSET;
return sNames.get(id);
@@ -495,7 +583,8 @@
* @param labels
* @return
*/
- public static String toString(float[] exp, String[] labels) {
+ @NonNull
+ public static String toString(@NonNull float[] exp, @Nullable String[] labels) {
StringBuilder s = new StringBuilder();
for (int i = 0; i < exp.length; i++) {
float v = exp[i];
@@ -525,7 +614,7 @@
return s.toString();
}
- static String toString(float[] exp, int sp) {
+ static String toString(@NonNull float[] exp, int sp) {
// String[] str = new String[exp.length];
if (Float.isNaN(exp[sp])) {
int id = fromNaN(exp[sp]) - OFFSET;
@@ -575,42 +664,42 @@
}
static final int[] NO_OF_OPS = {
- -1, // no op
- 2,
- 2,
- 2,
- 2,
- 2, // + - * / %
- 2,
- 2,
- 2, // min max, power
- 1,
- 1,
- 1,
- 1,
- 1,
- 1,
- 1,
- 1, // sqrt,abs,CopySign,exp,floor,log,ln
- 1,
- 1,
- 1,
- 1,
- 1,
- 1,
- 1,
- 2, // round,sin,cos,tan,asin,acos,atan,atan2
- 3,
- 3,
- 3,
- 1,
- 1,
- 1,
- 1,
- 0,
- 0,
- 0 // mad, ?:,
- // a[0],a[1],a[2]
+ -1, // no op
+ 2,
+ 2,
+ 2,
+ 2,
+ 2, // + - * / %
+ 2,
+ 2,
+ 2, // min max, power
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1, // sqrt,abs,CopySign,exp,floor,log,ln
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 2, // round,sin,cos,tan,asin,acos,atan,atan2
+ 3,
+ 3,
+ 3,
+ 1,
+ 1,
+ 1,
+ 1,
+ 0,
+ 0,
+ 0 // mad, ?:,
+ // a[0],a[1],a[2]
};
/**
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/ImageScaling.java b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/ImageScaling.java
index 00c87c1..e74b335 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/ImageScaling.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/ImageScaling.java
@@ -15,6 +15,8 @@
*/
package com.android.internal.widget.remotecompose.core.operations.utilities;
+import android.annotation.NonNull;
+
/** Implement the scaling logic for Compose Image or ImageView */
public class ImageScaling {
@@ -97,6 +99,7 @@
adjustDrawToType();
}
+ @NonNull
static String str(float v) {
String s = " " + (int) v;
return s.substring(s.length() - 3);
@@ -210,6 +213,7 @@
}
}
+ @NonNull
public static String typeToString(int type) {
String[] typeString = {
"none",
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/IntMap.java b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/IntMap.java
index 84e7843..749c0fe 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/IntMap.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/IntMap.java
@@ -15,6 +15,8 @@
*/
package com.android.internal.widget.remotecompose.core.operations.utilities;
+import android.annotation.Nullable;
+
import java.util.ArrayList;
import java.util.Arrays;
@@ -42,6 +44,7 @@
mSize = 0;
}
+ @Nullable
public T put(int key, T value) {
if (key == NOT_PRESENT) throw new IllegalArgumentException("Key cannot be NOT_PRESENT");
if (mSize > mKeys.length * LOAD_FACTOR) {
@@ -50,6 +53,7 @@
return insert(key, value);
}
+ @Nullable
public T get(int key) {
int index = findKey(key);
if (index == -1) {
@@ -61,6 +65,7 @@
return mSize;
}
+ @Nullable
private T insert(int key, T value) {
int index = hash(key) % mKeys.length;
while (mKeys[index] != NOT_PRESENT && mKeys[index] != key) {
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/IntegerExpressionEvaluator.java b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/IntegerExpressionEvaluator.java
index baa144d..8905431 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/IntegerExpressionEvaluator.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/IntegerExpressionEvaluator.java
@@ -15,6 +15,9 @@
*/
package com.android.internal.widget.remotecompose.core.operations.utilities;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
/**
* High performance Integer expression evaluator
*
@@ -22,7 +25,7 @@
* 0)
*/
public class IntegerExpressionEvaluator {
- static IntMap<String> sNames = new IntMap<>();
+ @NonNull static IntMap<String> sNames = new IntMap<>();
public static final int OFFSET = 0x10000;
// add, sub, mul,div,mod,min,max, shl, shr, ushr, OR, AND , XOR, COPY_SIGN
public static final int I_ADD = OFFSET + 1;
@@ -57,7 +60,7 @@
public static final int I_VAR2 = OFFSET + 25;
int[] mStack;
- int[] mLocalStack = new int[128];
+ @NonNull int[] mLocalStack = new int[128];
int[] mVar;
interface Op {
@@ -68,8 +71,8 @@
* Evaluate an integer expression
*
* @param mask bits that are operators
- * @param exp rpn sequence of values and operators
- * @param var variables if the expression is a function
+ * @param exp rpn sequence of values and operators
+ * @param var variables if the expression is a function
* @return return the results of evaluating the expression
*/
public int eval(int mask, int[] exp, int... var) {
@@ -91,12 +94,12 @@
* Evaluate a integer expression
*
* @param mask bits that are operators
- * @param exp rpn sequence of values and operators
- * @param len the number of values in the expression
- * @param var variables if the expression is a function
+ * @param exp rpn sequence of values and operators
+ * @param len the number of values in the expression
+ * @param var variables if the expression is a function
* @return return the results of evaluating the expression
*/
- public int eval(int mask, int[] exp, int len, int... var) {
+ public int eval(int mask, @NonNull int[] exp, int len, int... var) {
System.arraycopy(exp, 0, mLocalStack, 0, len);
mStack = mLocalStack;
mVar = var;
@@ -116,11 +119,11 @@
* Evaluate a int expression
*
* @param opMask bits that are operators
- * @param exp rpn sequence of values and operators
- * @param var variables if the expression is a function
+ * @param exp rpn sequence of values and operators
+ * @param var variables if the expression is a function
* @return return the results of evaluating the expression
*/
- public int evalDB(int opMask, int[] exp, int... var) {
+ public int evalDB(int opMask, @NonNull int[] exp, int... var) {
mStack = exp;
mVar = var;
int sp = -1;
@@ -137,113 +140,172 @@
return mStack[sp];
}
- Op[] mOps = {
+ @NonNull Op[] mOps;
+
+ {
+ Op mADD =
+ (sp) -> { // ADD
+ mStack[sp - 1] = mStack[sp - 1] + mStack[sp];
+ return sp - 1;
+ };
+ Op mSUB =
+ (sp) -> { // SUB
+ mStack[sp - 1] = mStack[sp - 1] - mStack[sp];
+ return sp - 1;
+ };
+ Op mMUL =
+ (sp) -> { // MUL
+ mStack[sp - 1] = mStack[sp - 1] * mStack[sp];
+ return sp - 1;
+ };
+ Op mDIV =
+ (sp) -> { // DIV
+ mStack[sp - 1] = mStack[sp - 1] / mStack[sp];
+ return sp - 1;
+ };
+ Op mMOD =
+ (sp) -> { // MOD
+ mStack[sp - 1] = mStack[sp - 1] % mStack[sp];
+ return sp - 1;
+ };
+ Op mSHL =
+ (sp) -> { // SHL
+ mStack[sp - 1] = mStack[sp - 1] << mStack[sp];
+ return sp - 1;
+ };
+ Op mSHR =
+ (sp) -> { // SHR
+ mStack[sp - 1] = mStack[sp - 1] >> mStack[sp];
+ return sp - 1;
+ };
+ Op mUSHR =
+ (sp) -> { // USHR
+ mStack[sp - 1] = mStack[sp - 1] >>> mStack[sp];
+ return sp - 1;
+ };
+ Op mOR =
+ (sp) -> { // OR
+ mStack[sp - 1] = mStack[sp - 1] | mStack[sp];
+ return sp - 1;
+ };
+ Op mAND =
+ (sp) -> { // AND
+ mStack[sp - 1] = mStack[sp - 1] & mStack[sp];
+ return sp - 1;
+ };
+ Op mXOR =
+ (sp) -> { // XOR
+ mStack[sp - 1] = mStack[sp - 1] ^ mStack[sp];
+ return sp - 1;
+ };
+ Op mCOPY_SIGN =
+ (sp) -> { // COPY_SIGN
+ mStack[sp - 1] = (mStack[sp - 1] ^ (mStack[sp] >> 31)) - (mStack[sp] >> 31);
+ return sp - 1;
+ };
+ Op mMIN =
+ (sp) -> { // MIN
+ mStack[sp - 1] = Math.min(mStack[sp - 1], mStack[sp]);
+ return sp - 1;
+ };
+ Op mMAX =
+ (sp) -> { // MAX
+ mStack[sp - 1] = Math.max(mStack[sp - 1], mStack[sp]);
+ return sp - 1;
+ };
+ Op mNEG =
+ (sp) -> { // NEG
+ mStack[sp] = -mStack[sp];
+ return sp;
+ };
+ Op mABS =
+ (sp) -> { // ABS
+ mStack[sp] = Math.abs(mStack[sp]);
+ return sp;
+ };
+ Op mINCR =
+ (sp) -> { // INCR
+ mStack[sp] = mStack[sp] + 1;
+ return sp;
+ };
+ Op mDECR =
+ (sp) -> { // DECR
+ mStack[sp] = mStack[sp] - 1;
+ return sp;
+ };
+ Op mNOT =
+ (sp) -> { // NOT
+ mStack[sp] = ~mStack[sp];
+ return sp;
+ };
+ Op mSIGN =
+ (sp) -> { // SIGN
+ mStack[sp] = (mStack[sp] >> 31) | (-mStack[sp] >>> 31);
+ return sp;
+ };
+ Op mCLAMP =
+ (sp) -> { // CLAMP
+ mStack[sp - 2] = Math.min(Math.max(mStack[sp - 2], mStack[sp]), mStack[sp - 1]);
+ return sp - 2;
+ };
+ Op mTERNARY_CONDITIONAL =
+ (sp) -> { // TERNARY_CONDITIONAL
+ mStack[sp - 2] = (mStack[sp] > 0) ? mStack[sp - 1] : mStack[sp - 2];
+ return sp - 2;
+ };
+ Op mMAD =
+ (sp) -> { // MAD
+ mStack[sp - 2] = mStack[sp] + mStack[sp - 1] * mStack[sp - 2];
+ return sp - 2;
+ };
+ Op mFIRST_VAR =
+ (sp) -> { // FIRST_VAR
+ mStack[sp] = mVar[0];
+ return sp;
+ };
+ Op mSECOND_VAR =
+ (sp) -> { // SECOND_VAR
+ mStack[sp] = mVar[1];
+ return sp;
+ };
+ Op mTHIRD_VAR =
+ (sp) -> { // THIRD_VAR
+ mStack[sp] = mVar[2];
+ return sp;
+ };
+
+ Op[] ops = {
null,
- (sp) -> { // ADD
- mStack[sp - 1] = mStack[sp - 1] + mStack[sp];
- return sp - 1;
- },
- (sp) -> { // SUB
- mStack[sp - 1] = mStack[sp - 1] - mStack[sp];
- return sp - 1;
- },
- (sp) -> { // MUL
- mStack[sp - 1] = mStack[sp - 1] * mStack[sp];
- return sp - 1;
- },
- (sp) -> { // DIV
- mStack[sp - 1] = mStack[sp - 1] / mStack[sp];
- return sp - 1;
- },
- (sp) -> { // MOD
- mStack[sp - 1] = mStack[sp - 1] % mStack[sp];
- return sp - 1;
- },
- (sp) -> { // SHL shift left
- mStack[sp - 1] = mStack[sp - 1] << mStack[sp];
- return sp - 1;
- },
- (sp) -> { // SHR shift right
- mStack[sp - 1] = mStack[sp - 1] >> mStack[sp];
- return sp - 1;
- },
- (sp) -> { // USHR unsigned shift right
- mStack[sp - 1] = mStack[sp - 1] >>> mStack[sp];
- return sp - 1;
- },
- (sp) -> { // OR operator
- mStack[sp - 1] = mStack[sp - 1] | mStack[sp];
- return sp - 1;
- },
- (sp) -> { // AND operator
- mStack[sp - 1] = mStack[sp - 1] & mStack[sp];
- return sp - 1;
- },
- (sp) -> { // XOR xor operator
- mStack[sp - 1] = mStack[sp - 1] ^ mStack[sp];
- return sp - 1;
- },
- (sp) -> { // COPY_SIGN copy the sing of (using bit magic)
- mStack[sp - 1] = (mStack[sp - 1] ^ (mStack[sp] >> 31)) - (mStack[sp] >> 31);
- return sp - 1;
- },
- (sp) -> { // MIN
- mStack[sp - 1] = Math.min(mStack[sp - 1], mStack[sp]);
- return sp - 1;
- },
- (sp) -> { // MAX
- mStack[sp - 1] = Math.max(mStack[sp - 1], mStack[sp]);
- return sp - 1;
- },
- (sp) -> { // NEG
- mStack[sp] = -mStack[sp];
- return sp;
- },
- (sp) -> { // ABS
- mStack[sp] = Math.abs(mStack[sp]);
- return sp;
- },
- (sp) -> { // INCR increment
- mStack[sp] = mStack[sp] + 1;
- return sp;
- },
- (sp) -> { // DECR decrement
- mStack[sp] = mStack[sp] - 1;
- return sp;
- },
- (sp) -> { // NOT Bit invert
- mStack[sp] = ~mStack[sp];
- return sp;
- },
- (sp) -> { // SIGN x<0 = -1,x==0 = 0 , x>0 = 1
- mStack[sp] = (mStack[sp] >> 31) | (-mStack[sp] >>> 31);
- return sp;
- },
- (sp) -> { // CLAMP(min,max, val)
- mStack[sp - 2] = Math.min(Math.max(mStack[sp - 2], mStack[sp]), mStack[sp - 1]);
- return sp - 2;
- },
- (sp) -> { // Ternary conditional
- mStack[sp - 2] = (mStack[sp] > 0) ? mStack[sp - 1] : mStack[sp - 2];
- return sp - 2;
- },
- (sp) -> { // MAD
- mStack[sp - 2] = mStack[sp] + mStack[sp - 1] * mStack[sp - 2];
- return sp - 2;
- },
- (sp) -> { // first var =
- mStack[sp] = mVar[0];
- return sp;
- },
- (sp) -> { // second var y?
- mStack[sp] = mVar[1];
- return sp;
- },
- (sp) -> { // 3rd var z?
- mStack[sp] = mVar[2];
- return sp;
- },
- };
+ mADD,
+ mSUB,
+ mMUL,
+ mDIV,
+ mMOD,
+ mSHL,
+ mSHR,
+ mUSHR,
+ mOR,
+ mAND,
+ mXOR,
+ mCOPY_SIGN,
+ mMIN,
+ mMAX,
+ mNEG,
+ mABS,
+ mINCR,
+ mDECR,
+ mNOT,
+ mSIGN,
+ mCLAMP,
+ mTERNARY_CONDITIONAL,
+ mMAD,
+ mFIRST_VAR,
+ mSECOND_VAR,
+ mTHIRD_VAR,
+ };
+
+ mOps = ops;
+ }
static {
int k = 0;
@@ -283,6 +345,7 @@
* @param f the numerical value of the function + offset
* @return the math name of the function
*/
+ @Nullable
public static String toMathName(int f) {
int id = f - OFFSET;
return sNames.get(id);
@@ -292,11 +355,12 @@
* Convert an expression encoded as an array of ints int to a string
*
* @param opMask bits that are operators
- * @param exp rpn sequence of values and operators
+ * @param exp rpn sequence of values and operators
* @param labels String that represent the variable names
* @return
*/
- public static String toString(int opMask, int[] exp, String[] labels) {
+ @NonNull
+ public static String toString(int opMask, @NonNull int[] exp, String[] labels) {
StringBuilder s = new StringBuilder();
for (int i = 0; i < exp.length; i++) {
int v = exp[i];
@@ -324,10 +388,11 @@
* Convert an expression encoded as an array of ints int ot a string
*
* @param opMask bit mask of operators vs commands
- * @param exp rpn sequence of values and operators
+ * @param exp rpn sequence of values and operators
* @return string representation of the expression
*/
- public static String toString(int opMask, int[] exp) {
+ @NonNull
+ public static String toString(int opMask, @NonNull int[] exp) {
StringBuilder s = new StringBuilder();
s.append(Integer.toBinaryString(opMask));
s.append(" : ");
@@ -355,13 +420,15 @@
* This creates an infix string expression
*
* @param opMask The bits that are operators
- * @param exp the array of expressions
+ * @param exp the array of expressions
* @return infix string
*/
- public static String toStringInfix(int opMask, int[] exp) {
+ @NonNull
+ public static String toStringInfix(int opMask, @NonNull int[] exp) {
return toString(opMask, exp, exp.length - 1);
}
+ @NonNull
static String toString(int mask, int[] exp, int sp) {
if (((1 << sp) & mask) != 0) {
int id = exp[sp] - OFFSET;
@@ -412,34 +479,34 @@
}
static final int[] NO_OF_OPS = {
- -1, // no op
- 2,
- 2,
- 2,
- 2,
- 2, // + - * / %
- 2,
- 2,
- 2,
- 2,
- 2,
- 2,
- 2,
- 2,
- 2, // <<, >> , >>> , | , &, ^, min max
- 1,
- 1,
- 1,
- 1,
- 1,
- 1, // neg, abs, ++, -- , not , sign
- 3,
- 3,
- 3, // clamp, ifElse, mad,
- 0,
- 0,
- 0 // mad, ?:,
- // a[0],a[1],a[2]
+ -1, // no op
+ 2,
+ 2,
+ 2,
+ 2,
+ 2, // + - * / %
+ 2,
+ 2,
+ 2,
+ 2,
+ 2,
+ 2,
+ 2,
+ 2,
+ 2, // <<, >> , >>> , | , &, ^, min max
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1, // neg, abs, ++, -- , not , sign
+ 3,
+ 3,
+ 3, // clamp, ifElse, mad,
+ 0,
+ 0,
+ 0 // mad, ?:,
+ // a[0],a[1],a[2]
};
/**
@@ -456,7 +523,7 @@
* is it an id or operation
*
* @param opMask the bits that mark elements as an operation
- * @param i the bit to check
+ * @param i the bit to check
* @return true if the bit is 1
*/
public static boolean isOperation(int opMask, int i) {
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/StringSerializer.java b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/StringSerializer.java
index ab7576e..92127c1 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/StringSerializer.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/StringSerializer.java
@@ -15,9 +15,14 @@
*/
package com.android.internal.widget.remotecompose.core.operations.utilities;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
/** Utility serializer maintaining an indent buffer */
public class StringSerializer {
- StringBuffer mBuffer = new StringBuffer();
+ @NonNull StringBuffer mBuffer = new StringBuffer();
+
+ @NonNull
String mIndentBuffer = " ";
/**
@@ -26,7 +31,7 @@
* @param indent the indentation level to use
* @param content content to append
*/
- public void append(int indent, String content) {
+ public void append(int indent, @Nullable String content) {
String indentation = mIndentBuffer.substring(0, indent);
mBuffer.append(indentation);
mBuffer.append(indentation);
@@ -44,6 +49,7 @@
*
* @return string representation
*/
+ @NonNull
@Override
public String toString() {
return mBuffer.toString();
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/StringUtils.java b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/StringUtils.java
index f2ccb40..a95a175 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/StringUtils.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/StringUtils.java
@@ -15,6 +15,8 @@
*/
package com.android.internal.widget.remotecompose.core.operations.utilities;
+import android.annotation.NonNull;
+
import java.util.Arrays;
/** Utilities for string manipulation */
@@ -30,6 +32,7 @@
* @param post character to pad width 0 = no pad typically ' ' or '0'
* @return
*/
+ @NonNull
public static String floatToString(
float value, int beforeDecimalPoint, int afterDecimalPoint, char pre, char post) {
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/easing/CubicEasing.java b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/easing/CubicEasing.java
index 60a59cf..1343345 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/easing/CubicEasing.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/easing/CubicEasing.java
@@ -15,6 +15,8 @@
*/
package com.android.internal.widget.remotecompose.core.operations.utilities.easing;
+import android.annotation.NonNull;
+
class CubicEasing extends Easing {
float mX1 = 0f;
float mY1 = 0f;
@@ -62,7 +64,7 @@
mType = type;
}
- void setup(float[] values) {
+ void setup(@NonNull float[] values) {
setup(values[0], values[1], values[2], values[3]);
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/easing/FloatAnimation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/easing/FloatAnimation.java
index a29b8af..ebb22b6 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/easing/FloatAnimation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/easing/FloatAnimation.java
@@ -15,6 +15,9 @@
*/
package com.android.internal.widget.remotecompose.core.operations.utilities.easing;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
/** Support Animation of the FloatExpression */
public class FloatAnimation extends Easing {
float[] mSpec;
@@ -31,6 +34,7 @@
// private float mScale = 1;
float mOffset = 0;
+ @NonNull
@Override
public String toString() {
@@ -74,7 +78,7 @@
* @return
*/
public static float[] packToFloatArray(
- float duration, int type, float[] spec, float initialValue, float wrap) {
+ float duration, int type, @Nullable float[] spec, float initialValue, float wrap) {
int count = 0;
if (!Float.isNaN(initialValue)) {
@@ -129,6 +133,90 @@
}
/**
+ * Useful to debug the packed form of an animation string
+ *
+ * @param description
+ * @return
+ */
+ public static String unpackAnimationToString(float[] description) {
+ float[] mSpec = description;
+ float mDuration = (mSpec.length == 0) ? 1 : mSpec[0];
+ int len = 0;
+ int type = 0;
+ float wrapValue = Float.NaN;
+ float initialValue = Float.NaN;
+ if (mSpec.length > 1) {
+ int num_type = Float.floatToRawIntBits(mSpec[1]);
+ type = num_type & 0xFF;
+ boolean wrap = ((num_type >> 8) & 0x1) > 0;
+ boolean init = ((num_type >> 8) & 0x2) > 0;
+ len = (num_type >> 16) & 0xFFFF;
+ int off = 2 + len;
+ if (init) {
+ initialValue = mSpec[off++];
+ }
+ if (wrap) {
+ wrapValue = mSpec[off];
+ }
+ }
+ float[] params = description;
+ int offset = 2;
+
+ String typeStr = "";
+ switch (type) {
+ case CUBIC_STANDARD:
+ typeStr = "CUBIC_STANDARD";
+ break;
+ case CUBIC_ACCELERATE:
+ typeStr = "CUBIC_ACCELERATE";
+ break;
+ case CUBIC_DECELERATE:
+ typeStr = "CUBIC_DECELERATE";
+ break;
+ case CUBIC_LINEAR:
+ typeStr = "CUBIC_LINEAR";
+ break;
+ case CUBIC_ANTICIPATE:
+ typeStr = "CUBIC_ANTICIPATE";
+ break;
+ case CUBIC_OVERSHOOT:
+ typeStr = "CUBIC_OVERSHOOT";
+
+ break;
+ case CUBIC_CUSTOM:
+ typeStr = "CUBIC_CUSTOM (";
+ typeStr += params[offset + 0] + " ";
+ typeStr += params[offset + 1] + " ";
+ typeStr += params[offset + 2] + " ";
+ typeStr += params[offset + 3] + " )";
+ break;
+ case EASE_OUT_BOUNCE:
+ typeStr = "EASE_OUT_BOUNCE";
+
+ break;
+ case EASE_OUT_ELASTIC:
+ typeStr = "EASE_OUT_ELASTIC";
+ break;
+ case SPLINE_CUSTOM:
+ typeStr = "SPLINE_CUSTOM (";
+ for (int i = offset; i < offset + len; i++) {
+ typeStr += params[i] + " ";
+ }
+ typeStr += ")";
+ break;
+ }
+
+ String str = mDuration + " " + typeStr;
+ if (!Float.isNaN(initialValue)) {
+ str += " init =" + initialValue;
+ }
+ if (!Float.isNaN(wrapValue)) {
+ str += " wrap =" + wrapValue;
+ }
+ return str;
+ }
+
+ /**
* Create an animation based on a float encoding of the animation
*
* @param description
@@ -208,21 +296,43 @@
setScaleOffset();
}
+ private static float wrap(float wrap, float value) {
+ value = value % wrap;
+ if (value < 0) {
+ value += wrap;
+ }
+ return value;
+ }
+
+ float wrapDistance(float wrap, float from, float to) {
+ float delta = (to - from) % 360;
+ if (delta < -wrap / 2) {
+ delta += wrap;
+ } else if (delta > wrap / 2) {
+ delta -= wrap;
+ }
+ return delta;
+ }
+
/**
* Set the target value to interpolate to
*
* @param value
*/
public void setTargetValue(float value) {
- if (Float.isNaN(mWrap)) {
- mTargetValue = value;
- } else {
- if (Math.abs((value % mWrap) + mWrap - mInitialValue)
- < Math.abs((value % mWrap) - mInitialValue)) {
- mTargetValue = (value % mWrap) + mWrap;
+ mTargetValue = value;
+ if (!Float.isNaN(mWrap)) {
+ mInitialValue = wrap(mWrap, mInitialValue);
+ mTargetValue = wrap(mWrap, mTargetValue);
+ if (Float.isNaN(mInitialValue)) {
+ mInitialValue = mTargetValue;
+ }
- } else {
- mTargetValue = value % mWrap;
+ float dist = wrapDistance(mWrap, mInitialValue, mTargetValue);
+ if ((dist > 0) && (mTargetValue < mInitialValue)) {
+ mTargetValue += mWrap;
+ } else if ((dist < 0) && (mTargetValue > mInitialValue)) {
+ mTargetValue -= mWrap;
}
}
setScaleOffset();
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/easing/GeneralEasing.java b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/easing/GeneralEasing.java
index 75a6032..90b65bf 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/easing/GeneralEasing.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/easing/GeneralEasing.java
@@ -15,10 +15,12 @@
*/
package com.android.internal.widget.remotecompose.core.operations.utilities.easing;
+import android.annotation.NonNull;
+
/** Provides and interface to create easing functions */
public class GeneralEasing extends Easing {
float[] mEasingData = new float[0];
- Easing mEasingCurve = new CubicEasing(CUBIC_STANDARD);
+ @NonNull Easing mEasingCurve = new CubicEasing(CUBIC_STANDARD);
/**
* Set the curve based on the float encoding of it
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/easing/MonotonicCurveFit.java b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/easing/MonotonicCurveFit.java
index 9355cac..f540e70 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/easing/MonotonicCurveFit.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/easing/MonotonicCurveFit.java
@@ -15,6 +15,8 @@
*/
package com.android.internal.widget.remotecompose.core.operations.utilities.easing;
+import android.annotation.NonNull;
+
import java.util.Arrays;
/** This performs a spline interpolation in multiple dimensions */
@@ -32,7 +34,7 @@
* @param time the point along the curve
* @param y the parameter at those points
*/
- public MonotonicCurveFit(double[] time, double[][] y) {
+ public MonotonicCurveFit(@NonNull double[] time, @NonNull double[][] y) {
final int n = time.length;
final int dim = y[0].length;
mSlopeTemp = new double[dim];
@@ -331,7 +333,8 @@
}
/** This builds a monotonic spline to be used as a wave function */
- public static MonotonicCurveFit buildWave(String configString) {
+ @NonNull
+ public static MonotonicCurveFit buildWave(@NonNull String configString) {
// done this way for efficiency
String str = configString;
double[] values = new double[str.length() / 2];
@@ -350,7 +353,8 @@
return buildWave(Arrays.copyOf(values, count));
}
- private static MonotonicCurveFit buildWave(double[] values) {
+ @NonNull
+ private static MonotonicCurveFit buildWave(@NonNull double[] values) {
int length = values.length * 3 - 2;
int len = values.length - 1;
double gap = 1.0 / len;
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/easing/StepCurve.java b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/easing/StepCurve.java
index b459689..c7be3ca 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/easing/StepCurve.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/easing/StepCurve.java
@@ -15,6 +15,8 @@
*/
package com.android.internal.widget.remotecompose.core.operations.utilities.easing;
+import android.annotation.NonNull;
+
/**
* This class translates a series of floating point values into a continuous curve for use in an
* easing function including quantize functions it is used with the "spline(0,0.3,0.3,0.5,...0.9,1)"
@@ -28,6 +30,7 @@
mCurveFit = genSpline(params, offset, len);
}
+ @NonNull
private static MonotonicCurveFit genSpline(float[] values, int off, int arrayLen) {
int length = arrayLen * 3 - 2;
int len = arrayLen - 1;
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/touch/VelocityEasing.java b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/touch/VelocityEasing.java
new file mode 100644
index 0000000..3e24372
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/touch/VelocityEasing.java
@@ -0,0 +1,341 @@
+/*
+ * Copyright (C) 2024 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.internal.widget.remotecompose.core.operations.utilities.touch;
+
+/*
+ * Copyright (C) 2024 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.
+ */
+
+public class VelocityEasing {
+ private float mStartPos = 0;
+ private float mStartV = 0;
+ private float mEndPos = 0;
+ private float mDuration = 0;
+
+ private Stage[] mStage = {new Stage(1), new Stage(2), new Stage(3)};
+ private int mNumberOfStages = 0;
+ private Easing mEasing;
+ private double mEasingAdapterDistance = 0;
+ private double mEasingAdapterA = 0;
+ private double mEasingAdapterB = 0;
+ private boolean mOneDimension = true;
+ private float mTotalEasingDuration = 0;
+
+ public float getDuration() {
+ if (mEasing != null) {
+ return mTotalEasingDuration;
+ }
+ return mDuration;
+ }
+
+ public float getV(float t) {
+ if (mEasing == null) {
+ for (int i = 0; i < mNumberOfStages; i++) {
+ if (mStage[i].mEndTime > t) {
+ return mStage[i].getVel(t);
+ }
+ }
+ return 0f;
+ }
+ int lastStages = mNumberOfStages - 1;
+ for (int i = 0; i < lastStages; i++) {
+ if (mStage[i].mEndTime > t) {
+ return mStage[i].getVel(t);
+ }
+ }
+ return (float) getEasingDiff((t - mStage[lastStages].mStartTime));
+ }
+
+ public float getPos(float t) {
+ if (mEasing == null) {
+ for (int i = 0; i < mNumberOfStages; i++) {
+ if (mStage[i].mEndTime > t) {
+ return mStage[i].getPos(t);
+ }
+ }
+ return mEndPos;
+ }
+ int lastStages = mNumberOfStages - 1;
+ for (int i = 0; i < lastStages; i++) {
+ if (mStage[i].mEndTime > t) {
+ return mStage[i].getPos(t);
+ }
+ }
+ var ret = (float) getEasing((t - mStage[lastStages].mStartTime));
+ ret += mStage[lastStages].mStartPos;
+ return ret;
+ }
+
+ public String toString() {
+ var s = " ";
+ for (int i = 0; i < mNumberOfStages; i++) {
+ Stage stage = mStage[i];
+ s += " $i $stage";
+ }
+ return s;
+ }
+
+ public void config(
+ float currentPos,
+ float destination,
+ float currentVelocity,
+ float maxTime,
+ float maxAcceleration,
+ float maxVelocity,
+ Easing easing) {
+ float pos = currentPos;
+ float velocity = currentVelocity;
+ if (pos == destination) {
+ pos += 1f;
+ }
+ mStartPos = pos;
+ mEndPos = destination;
+ if (easing != null) {
+ this.mEasing = easing.clone();
+ }
+ float dir = Math.signum(destination - pos);
+ float maxV = maxVelocity * dir;
+ float maxA = maxAcceleration * dir;
+ if (velocity == 0.0) {
+ velocity = 0.0001f * dir;
+ }
+ mStartV = velocity;
+ if (!rampDown(pos, destination, velocity, maxTime)) {
+ if (!(mOneDimension
+ && cruseThenRampDown(pos, destination, velocity, maxTime, maxA, maxV))) {
+ if (!rampUpRampDown(pos, destination, velocity, maxA, maxV, maxTime)) {
+ rampUpCruseRampDown(pos, destination, velocity, maxA, maxV, maxTime);
+ }
+ }
+ }
+ if (mOneDimension) {
+ configureEasingAdapter();
+ }
+ }
+
+ private boolean rampDown(
+ float currentPos, float destination, float currentVelocity, float maxTime) {
+ float timeToDestination = 2 * ((destination - currentPos) / currentVelocity);
+ if (timeToDestination > 0 && timeToDestination <= maxTime) { // hit the brakes
+ mNumberOfStages = 1;
+ mStage[0].setUp(currentVelocity, currentPos, 0f, 0f, destination, timeToDestination);
+ mDuration = timeToDestination;
+ return true;
+ }
+ return false;
+ }
+
+ private boolean cruseThenRampDown(
+ float currentPos,
+ float destination,
+ float currentVelocity,
+ float maxTime,
+ float maxA,
+ float maxV) {
+ float timeToBreak = currentVelocity / maxA;
+ float brakeDist = currentVelocity * timeToBreak / 2;
+ float cruseDist = destination - currentPos - brakeDist;
+ float cruseTime = cruseDist / currentVelocity;
+ float totalTime = cruseTime + timeToBreak;
+ if (totalTime > 0 && totalTime < maxTime) {
+ mNumberOfStages = 2;
+ mStage[0].setUp(currentVelocity, currentPos, 0f, currentVelocity, cruseDist, cruseTime);
+ mStage[1].setUp(
+ currentVelocity,
+ currentPos + cruseDist,
+ cruseTime,
+ 0f,
+ destination,
+ cruseTime + timeToBreak);
+ mDuration = cruseTime + timeToBreak;
+ return true;
+ }
+ return false;
+ }
+
+ private boolean rampUpRampDown(
+ float currentPos,
+ float destination,
+ float currentVelocity,
+ float maxA,
+ float maxVelocity,
+ float maxTime) {
+ float peak_v =
+ Math.signum(maxA)
+ * (float)
+ Math.sqrt(
+ (maxA * (destination - currentPos)
+ + currentVelocity * currentVelocity / 2));
+ if (maxVelocity / peak_v > 1) {
+ float t1 = (peak_v - currentVelocity) / maxA;
+ float d1 = (peak_v + currentVelocity) * t1 / 2 + currentPos;
+ float t2 = peak_v / maxA;
+ mNumberOfStages = 2;
+ mStage[0].setUp(currentVelocity, currentPos, 0f, peak_v, d1, t1);
+ mStage[1].setUp(peak_v, d1, t1, 0f, destination, t2 + t1);
+ mDuration = t2 + t1;
+ if (mDuration > maxTime) {
+ return false;
+ }
+ if (mDuration < maxTime / 2) {
+ t1 = mDuration / 2;
+ t2 = t1;
+ peak_v = (2 * (destination - currentPos) / t1 - currentVelocity) / 2;
+ d1 = (peak_v + currentVelocity) * t1 / 2 + currentPos;
+ mNumberOfStages = 2;
+ mStage[0].setUp(currentVelocity, currentPos, 0f, peak_v, d1, t1);
+ mStage[1].setUp(peak_v, d1, t1, 0f, destination, t2 + t1);
+ mDuration = t2 + t1;
+ if (mDuration > maxTime) {
+ System.out.println(" fail ");
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ private void rampUpCruseRampDown(
+ float currentPos,
+ float destination,
+ float currentVelocity,
+ float maxA,
+ float maxV,
+ float maxTime) {
+ float t1 = maxTime / 3;
+ float t2 = t1 * 2;
+ float distance = destination - currentPos;
+ float dt2 = t2 - t1;
+ float dt3 = maxTime - t2;
+ float v1 = (2 * distance - currentVelocity * t1) / (t1 + 2 * dt2 + dt3);
+ mDuration = maxTime;
+ float d1 = (currentVelocity + v1) * t1 / 2;
+ float d2 = (v1 + v1) * (t2 - t1) / 2;
+ mNumberOfStages = 3;
+ float acc = (v1 - currentVelocity) / t1;
+ float dec = v1 / dt3;
+ mStage[0].setUp(currentVelocity, currentPos, 0f, v1, currentPos + d1, t1);
+ mStage[1].setUp(v1, currentPos + d1, t1, v1, currentPos + d1 + d2, t2);
+ mStage[2].setUp(v1, currentPos + d1 + d2, t2, 0f, destination, maxTime);
+ mDuration = maxTime;
+ }
+
+ double getEasing(double t) {
+ double gx = t * t * mEasingAdapterA + t * mEasingAdapterB;
+ if (gx > 1) {
+ return mEasingAdapterDistance;
+ } else {
+ return mEasing.get(gx) * mEasingAdapterDistance;
+ }
+ }
+
+ private double getEasingDiff(double t) {
+ double gx = t * t * mEasingAdapterA + t * mEasingAdapterB;
+ if (gx > 1) {
+ return 0.0;
+ } else {
+ return mEasing.getDiff(gx)
+ * mEasingAdapterDistance
+ * (t * mEasingAdapterA + mEasingAdapterB);
+ }
+ }
+
+ protected void configureEasingAdapter() {
+ if (mEasing == null) {
+ return;
+ }
+ int last = mNumberOfStages - 1;
+ float initialVelocity = mStage[last].mStartV;
+ float distance = mStage[last].mEndPos - mStage[last].mStartPos;
+ float duration = mStage[last].mEndTime - mStage[last].mStartTime;
+ double baseVel = mEasing.getDiff(0.0);
+ mEasingAdapterB = initialVelocity / (baseVel * distance);
+ mEasingAdapterA = 1 - mEasingAdapterB;
+ mEasingAdapterDistance = distance;
+ double easingDuration =
+ (Math.sqrt(4 * mEasingAdapterA + mEasingAdapterB * mEasingAdapterB)
+ - mEasingAdapterB)
+ / (2 * mEasingAdapterA);
+ mTotalEasingDuration = (float) (easingDuration + mStage[last].mStartTime);
+ }
+
+ interface Easing {
+ double get(double t);
+
+ double getDiff(double t);
+
+ Easing clone();
+ }
+
+ class Stage {
+ private float mStartV = 0;
+ private float mStartPos = 0;
+ private float mStartTime = 0;
+ private float mEndV = 0;
+ private float mEndPos = 0;
+ private float mEndTime = 0;
+ private float mDeltaV = 0;
+ private float mDeltaT = 0;
+ final int mStage;
+
+ Stage(int n) {
+ mStage = n;
+ }
+
+ void setUp(
+ float startV,
+ float startPos,
+ float startTime,
+ float endV,
+ float endPos,
+ float endTime) {
+ this.mStartV = startV;
+ this.mStartPos = startPos;
+ this.mStartTime = startTime;
+ this.mEndV = endV;
+ this.mEndTime = endTime;
+ this.mEndPos = endPos;
+ mDeltaV = this.mEndV - this.mStartV;
+ mDeltaT = this.mEndTime - this.mStartTime;
+ }
+
+ float getPos(float t) {
+ float dt = t - mStartTime;
+ float pt = dt / mDeltaT;
+ float v = mStartV + mDeltaV * pt;
+ return dt * (mStartV + v) / 2 + mStartPos;
+ }
+
+ float getVel(float t) {
+ float dt = t - mStartTime;
+ float pt = dt / (mEndTime - mStartTime);
+ return mStartV + mDeltaV * pt;
+ }
+ }
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/types/BooleanConstant.java b/core/java/com/android/internal/widget/remotecompose/core/types/BooleanConstant.java
index 57a8042..3fba8ac 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/types/BooleanConstant.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/types/BooleanConstant.java
@@ -17,6 +17,8 @@
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.BYTE;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.RemoteContext;
@@ -47,23 +49,26 @@
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(buffer, mId, mValue);
}
@Override
public void apply(RemoteContext context) {}
+ @NonNull
@Override
public String deepToString(String indent) {
return toString();
}
+ @NonNull
@Override
public String toString() {
return "BooleanConstant[" + mId + "] = " + mValue + "";
}
+ @NonNull
public static String name() {
return "OrigamiBoolean";
}
@@ -79,20 +84,20 @@
* @param id
* @param value
*/
- public static void apply(WireBuffer buffer, int id, boolean value) {
+ public static void apply(@NonNull WireBuffer buffer, int id, boolean value) {
buffer.start(OP_CODE);
buffer.writeInt(id);
buffer.writeBoolean(value);
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int id = buffer.readInt();
boolean value = buffer.readBoolean();
operations.add(new BooleanConstant(id, value));
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Expressions Operations", OP_CODE, "BooleanConstant")
.description("A boolean and its associated id")
.field(DocumentedOperation.INT, "id", "id of Int")
diff --git a/core/java/com/android/internal/widget/remotecompose/core/types/IntegerConstant.java b/core/java/com/android/internal/widget/remotecompose/core/types/IntegerConstant.java
index 3ef9db9..79f2a8d 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/types/IntegerConstant.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/types/IntegerConstant.java
@@ -17,6 +17,8 @@
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.RemoteContext;
@@ -37,25 +39,28 @@
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(buffer, mId, mValue);
}
@Override
- public void apply(RemoteContext context) {
+ public void apply(@NonNull RemoteContext context) {
context.loadInteger(mId, mValue);
}
+ @NonNull
@Override
public String deepToString(String indent) {
return toString();
}
+ @NonNull
@Override
public String toString() {
return "IntegerConstant[" + mId + "] = " + mValue + "";
}
+ @NonNull
public static String name() {
return "IntegerConstant";
}
@@ -71,20 +76,20 @@
* @param textId
* @param value
*/
- public static void apply(WireBuffer buffer, int textId, int value) {
+ public static void apply(@NonNull WireBuffer buffer, int textId, int value) {
buffer.start(Operations.DATA_INT);
buffer.writeInt(textId);
buffer.writeInt(value);
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int id = buffer.readInt();
int value = buffer.readInt();
operations.add(new IntegerConstant(id, value));
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Expressions Operations", id(), "IntegerConstant")
.description("A integer and its associated id")
.field(DocumentedOperation.INT, "id", "id of Int")
diff --git a/core/java/com/android/internal/widget/remotecompose/core/types/LongConstant.java b/core/java/com/android/internal/widget/remotecompose/core/types/LongConstant.java
index 6d51d19..01672b4 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/types/LongConstant.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/types/LongConstant.java
@@ -17,6 +17,8 @@
import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.LONG;
+import android.annotation.NonNull;
+
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.RemoteContext;
@@ -47,7 +49,7 @@
}
@Override
- public void write(WireBuffer buffer) {
+ public void write(@NonNull WireBuffer buffer) {
apply(buffer, mId, mValue);
}
@@ -56,11 +58,13 @@
context.putObject(mId, this);
}
+ @NonNull
@Override
public String deepToString(String indent) {
return toString();
}
+ @NonNull
@Override
public String toString() {
return "LongConstant[" + mId + "] = " + mValue + "";
@@ -73,20 +77,20 @@
* @param id
* @param value
*/
- public static void apply(WireBuffer buffer, int id, long value) {
+ public static void apply(@NonNull WireBuffer buffer, int id, long value) {
buffer.start(OP_CODE);
buffer.writeInt(id);
buffer.writeLong(value);
}
- public static void read(WireBuffer buffer, List<Operation> operations) {
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int id = buffer.readInt();
long value = buffer.readLong();
operations.add(new LongConstant(id, value));
}
- public static void documentation(DocumentationBuilder doc) {
+ public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Expressions Operations", OP_CODE, "LongConstant")
.description("A boolean and its associated id")
.field(DocumentedOperation.INT, "id", "id of Int")
diff --git a/core/java/com/android/internal/widget/remotecompose/player/RemoteComposeDocument.java b/core/java/com/android/internal/widget/remotecompose/player/RemoteComposeDocument.java
index 906282c..aaee9c5 100644
--- a/core/java/com/android/internal/widget/remotecompose/player/RemoteComposeDocument.java
+++ b/core/java/com/android/internal/widget/remotecompose/player/RemoteComposeDocument.java
@@ -112,6 +112,16 @@
}
/**
+ * Gets a array of Names of the named variables of a specific type defined in the doc.
+ *
+ * @param type the type of variable NamedVariable.COLOR_TYPE, STRING_TYPE, etc
+ * @return array of name or null
+ */
+ public String[] getNamedVariables(int type) {
+ return mDocument.getNamedVariables(type);
+ }
+
+ /**
* Return a component associated with id
*
* @param id the component id
diff --git a/core/java/com/android/internal/widget/remotecompose/player/RemoteComposePlayer.java b/core/java/com/android/internal/widget/remotecompose/player/RemoteComposePlayer.java
index 06bf4cd..cc74b11 100644
--- a/core/java/com/android/internal/widget/remotecompose/player/RemoteComposePlayer.java
+++ b/core/java/com/android/internal/widget/remotecompose/player/RemoteComposePlayer.java
@@ -21,11 +21,14 @@
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
+import android.view.HapticFeedbackConstants;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.HorizontalScrollView;
import android.widget.ScrollView;
+import com.android.internal.widget.remotecompose.core.CoreDocument;
+import com.android.internal.widget.remotecompose.core.operations.NamedVariable;
import com.android.internal.widget.remotecompose.core.operations.RootContentBehavior;
import com.android.internal.widget.remotecompose.player.platform.RemoteComposeCanvas;
@@ -57,11 +60,7 @@
* @param debugFlags 1 to set debug on
*/
public void setDebug(int debugFlags) {
- if (debugFlags == 1) {
- mInner.setDebug(true);
- } else {
- mInner.setDebug(false);
- }
+ mInner.setDebug(debugFlags);
}
public RemoteComposeDocument getDocument() {
@@ -82,6 +81,14 @@
mInner.setDocument(null);
}
mapColors();
+ mInner.setHapticEngine(
+ new CoreDocument.HapticEngine() {
+
+ @Override
+ public void haptic(int type) {
+ provideHapticFeedback(type);
+ }
+ });
}
/**
@@ -259,13 +266,40 @@
/**
* This returns a list of colors that have names in the Document.
*
- * @return
+ * @return the names of named Strings or null
*/
public String[] getNamedColors() {
return mInner.getNamedColors();
}
/**
+ * This returns a list of floats that have names in the Document.
+ *
+ * @return return the names of named floats in the document
+ */
+ public String[] getNamedFloats() {
+ return mInner.getNamedVariables(NamedVariable.FLOAT_TYPE);
+ }
+
+ /**
+ * This returns a list of string name that have names in the Document.
+ *
+ * @return the name of named string (not the string itself)
+ */
+ public String[] getNamedStrings() {
+ return mInner.getNamedVariables(NamedVariable.STRING_TYPE);
+ }
+
+ /**
+ * This returns a list of images that have names in the Document.
+ *
+ * @return
+ */
+ public String[] getNamedImages() {
+ return mInner.getNamedVariables(NamedVariable.IMAGE_TYPE);
+ }
+
+ /**
* This sets a color based on its name. Overriding the color set in the document.
*
* @param colorName Name of the color
@@ -481,4 +515,32 @@
return color;
}
}
+
+ private static int[] sHapticTable = {
+ HapticFeedbackConstants.NO_HAPTICS,
+ HapticFeedbackConstants.LONG_PRESS,
+ HapticFeedbackConstants.VIRTUAL_KEY,
+ HapticFeedbackConstants.KEYBOARD_TAP,
+ HapticFeedbackConstants.CLOCK_TICK,
+ HapticFeedbackConstants.CONTEXT_CLICK,
+ HapticFeedbackConstants.KEYBOARD_PRESS,
+ HapticFeedbackConstants.KEYBOARD_RELEASE,
+ HapticFeedbackConstants.VIRTUAL_KEY_RELEASE,
+ HapticFeedbackConstants.TEXT_HANDLE_MOVE,
+ HapticFeedbackConstants.GESTURE_START,
+ HapticFeedbackConstants.GESTURE_END,
+ HapticFeedbackConstants.CONFIRM,
+ HapticFeedbackConstants.REJECT,
+ HapticFeedbackConstants.TOGGLE_ON,
+ HapticFeedbackConstants.TOGGLE_OFF,
+ HapticFeedbackConstants.GESTURE_THRESHOLD_ACTIVATE,
+ HapticFeedbackConstants.GESTURE_THRESHOLD_DEACTIVATE,
+ HapticFeedbackConstants.DRAG_START,
+ HapticFeedbackConstants.SEGMENT_TICK,
+ HapticFeedbackConstants.SEGMENT_FREQUENT_TICK,
+ };
+
+ private void provideHapticFeedback(int type) {
+ performHapticFeedback(sHapticTable[type % sHapticTable.length]);
+ }
}
diff --git a/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidPaintContext.java b/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidPaintContext.java
index f59a0d3..0b650a9 100644
--- a/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidPaintContext.java
+++ b/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidPaintContext.java
@@ -26,6 +26,8 @@
import android.graphics.RadialGradient;
import android.graphics.Rect;
import android.graphics.RectF;
+import android.graphics.RenderEffect;
+import android.graphics.RenderNode;
import android.graphics.RuntimeShader;
import android.graphics.Shader;
import android.graphics.SweepGradient;
@@ -51,6 +53,8 @@
List<Paint> mPaintList = new ArrayList<>();
Canvas mCanvas;
Rect mTmpRect = new Rect(); // use in calculation of bounds
+ RenderNode mNode = null;
+ Canvas mPreviousCanvas = null;
public AndroidPaintContext(RemoteContext context, Canvas canvas) {
super(context);
@@ -122,6 +126,53 @@
}
@Override
+ public void startGraphicsLayer(int w, int h) {
+ mNode = new RenderNode("layer");
+ mNode.setPosition(0, 0, w, h);
+ mPreviousCanvas = mCanvas;
+ mCanvas = mNode.beginRecording();
+ }
+
+ @Override
+ public void setGraphicsLayer(
+ float scaleX,
+ float scaleY,
+ float rotationX,
+ float rotationY,
+ float rotationZ,
+ float shadowElevation,
+ float transformOriginX,
+ float transformOriginY,
+ float alpha,
+ int renderEffectId) {
+ if (mNode == null) {
+ return;
+ }
+ mNode.setScaleX(scaleX);
+ mNode.setScaleY(scaleY);
+ mNode.setRotationX(rotationX);
+ mNode.setRotationY(rotationY);
+ mNode.setRotationZ(rotationZ);
+ mNode.setPivotX(transformOriginX * mNode.getWidth());
+ mNode.setPivotY(transformOriginY * mNode.getHeight());
+ mNode.setAlpha(alpha);
+ if (renderEffectId == 1) {
+
+ RenderEffect effect = RenderEffect.createBlurEffect(8f, 8f, Shader.TileMode.CLAMP);
+ mNode.setRenderEffect(effect);
+ }
+ }
+
+ @Override
+ public void endGraphicsLayer() {
+ mNode.endRecording();
+ mCanvas = mPreviousCanvas;
+ mCanvas.drawRenderNode(mNode);
+ // node.discardDisplayList();
+ mNode = null;
+ }
+
+ @Override
public void translate(float translateX, float translateY) {
mCanvas.translate(translateX, translateY);
}
@@ -241,6 +292,8 @@
if (start != 0) {
textToPaint = textToPaint.substring(start);
}
+ } else if (end > textToPaint.length()) {
+ textToPaint = textToPaint.substring(start);
} else {
textToPaint = textToPaint.substring(start, end);
}
diff --git a/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidPlatformServices.java b/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidPlatformServices.java
index f9b22a2..f28e85a 100644
--- a/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidPlatformServices.java
+++ b/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidPlatformServices.java
@@ -18,6 +18,7 @@
import android.graphics.Bitmap;
import android.graphics.Path;
import android.graphics.PathIterator;
+import android.util.Log;
import com.android.internal.widget.remotecompose.core.Platform;
import com.android.internal.widget.remotecompose.core.operations.PathData;
@@ -27,6 +28,8 @@
/** Services that are needed to be provided by the platform during encoding. */
public class AndroidPlatformServices implements Platform {
+ private static final String LOG_TAG = "RemoteCompose";
+
@Override
public byte[] imageToByteArray(Object image) {
if (image instanceof Bitmap) {
@@ -67,6 +70,24 @@
return null;
}
+ @Override
+ public void log(LogCategory category, String message) {
+ switch (category) {
+ case DEBUG:
+ Log.d(LOG_TAG, message);
+ break;
+ case INFO:
+ Log.i(LOG_TAG, message);
+ break;
+ case WARN:
+ Log.w(LOG_TAG, message);
+ break;
+ default:
+ Log.e(LOG_TAG, message);
+ break;
+ }
+ }
+
private float[] androidPathToFloatArray(Path path) {
PathIterator i = path.getPathIterator();
int estimatedSize = 0;
diff --git a/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidRemoteContext.java b/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidRemoteContext.java
index e7c0cc8..7a7edba 100644
--- a/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidRemoteContext.java
+++ b/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidRemoteContext.java
@@ -20,6 +20,7 @@
import android.graphics.Canvas;
import com.android.internal.widget.remotecompose.core.RemoteContext;
+import com.android.internal.widget.remotecompose.core.TouchListener;
import com.android.internal.widget.remotecompose.core.VariableSupport;
import com.android.internal.widget.remotecompose.core.operations.FloatExpression;
import com.android.internal.widget.remotecompose.core.operations.ShaderData;
@@ -143,9 +144,9 @@
}
@Override
- public void runNamedAction(int id) {
+ public void runNamedAction(int id, Object value) {
String text = getText(id);
- mDocument.runNamedAction(text);
+ mDocument.runNamedAction(text, value);
}
/**
@@ -200,6 +201,11 @@
}
@Override
+ public void overrideFloat(int id, float value) {
+ mRemoteComposeState.overrideFloat(id, value);
+ }
+
+ @Override
public void loadInteger(int id, int value) {
mRemoteComposeState.updateInteger(id, value);
}
@@ -268,6 +274,11 @@
return (ShaderData) mRemoteComposeState.getFromId(id);
}
+ @Override
+ public void addTouchListener(TouchListener touchExpression) {
+ mDocument.addTouchListener(touchExpression);
+ }
+
///////////////////////////////////////////////////////////////////////////////////////////////
// Click handling
///////////////////////////////////////////////////////////////////////////////////////////////
@@ -285,4 +296,8 @@
String metadata = (String) mRemoteComposeState.getFromId(metadataId);
mDocument.addClickArea(id, contentDescription, left, top, right, bottom, metadata);
}
+
+ public void hapticEffect(int type) {
+ mDocument.haptic(type);
+ }
}
diff --git a/core/java/com/android/internal/widget/remotecompose/player/platform/RemoteComposeCanvas.java b/core/java/com/android/internal/widget/remotecompose/player/platform/RemoteComposeCanvas.java
index 7de6988..b54ed8a 100644
--- a/core/java/com/android/internal/widget/remotecompose/player/platform/RemoteComposeCanvas.java
+++ b/core/java/com/android/internal/widget/remotecompose/player/platform/RemoteComposeCanvas.java
@@ -21,6 +21,7 @@
import android.graphics.Point;
import android.util.AttributeSet;
import android.view.MotionEvent;
+import android.view.VelocityTracker;
import android.view.View;
import android.widget.FrameLayout;
@@ -38,7 +39,7 @@
RemoteComposeDocument mDocument = null;
int mTheme = Theme.LIGHT;
boolean mInActionDown = false;
- boolean mDebug = false;
+ int mDebug = 0;
boolean mHasClickAreas = false;
Point mActionDownPoint = new Point(0, 0);
AndroidRemoteContext mARContext = new AndroidRemoteContext();
@@ -65,14 +66,14 @@
}
}
- public void setDebug(boolean value) {
+ public void setDebug(int value) {
if (mDebug != value) {
mDebug = value;
if (USE_VIEW_AREA_CLICK) {
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
if (child instanceof ClickAreaView) {
- ((ClickAreaView) child).setDebug(mDebug);
+ ((ClickAreaView) child).setDebug(mDebug == 1);
}
}
}
@@ -107,7 +108,7 @@
ClickAreaView viewArea =
new ClickAreaView(
getContext(),
- mDebug,
+ mDebug == 1,
area.getId(),
area.getContentDescription(),
area.getMetadata());
@@ -128,6 +129,10 @@
}
}
+ public void setHapticEngine(CoreDocument.HapticEngine engine) {
+ mDocument.getDocument().setHapticEngine(engine);
+ }
+
@Override
public void onViewDetachedFromWindow(View view) {
removeAllViews();
@@ -138,6 +143,16 @@
}
/**
+ * Gets a array of Names of the named variables of a specific type defined in the loaded doc.
+ *
+ * @param type the type of variable NamedVariable.COLOR_TYPE, STRING_TYPE, etc
+ * @return array of name or null
+ */
+ public String[] getNamedVariables(int type) {
+ return mDocument.getNamedVariables(type);
+ }
+
+ /**
* set the color associated with this name.
*
* @param colorName Name of color typically "android.xxx"
@@ -198,7 +213,12 @@
this.mTheme = theme;
}
+ private VelocityTracker mVelocityTracker = null;
+
public boolean onTouchEvent(MotionEvent event) {
+ int index = event.getActionIndex();
+ int action = event.getActionMasked();
+ int pointerId = event.getPointerId(index);
if (USE_VIEW_AREA_CLICK && mHasClickAreas) {
return super.onTouchEvent(event);
}
@@ -207,15 +227,51 @@
mActionDownPoint.x = (int) event.getX();
mActionDownPoint.y = (int) event.getY();
mInActionDown = true;
+ CoreDocument doc = mDocument.getDocument();
+ if (doc.hasTouchListener()) {
+ if (mVelocityTracker == null) {
+ mVelocityTracker = VelocityTracker.obtain();
+ } else {
+ mVelocityTracker.clear();
+ }
+ mVelocityTracker.addMovement(event);
+ doc.touchDown(mARContext, event.getX(), event.getY());
+ }
return true;
+
case MotionEvent.ACTION_CANCEL:
mInActionDown = false;
+ doc = mDocument.getDocument();
+ if (doc.hasTouchListener()) {
+ mVelocityTracker.computeCurrentVelocity(1000);
+ float dx = mVelocityTracker.getXVelocity(pointerId);
+ float dy = mVelocityTracker.getYVelocity(pointerId);
+ doc.touchCancel(mARContext, event.getX(), event.getY(), dx, dy);
+ }
return true;
case MotionEvent.ACTION_UP:
mInActionDown = false;
performClick();
+ doc = mDocument.getDocument();
+ if (doc.hasTouchListener()) {
+ mVelocityTracker.computeCurrentVelocity(1000);
+ float dx = mVelocityTracker.getXVelocity(pointerId);
+ float dy = mVelocityTracker.getYVelocity(pointerId);
+ doc.touchUp(mARContext, event.getX(), event.getY(), dx, dy);
+ }
return true;
+
case MotionEvent.ACTION_MOVE:
+ if (mInActionDown) {
+ if (mVelocityTracker != null) {
+ mVelocityTracker.addMovement(event);
+ doc = mDocument.getDocument();
+ boolean repaint = doc.touchDrag(mARContext, event.getX(), event.getY());
+ if (repaint) {
+ invalidate();
+ }
+ }
+ }
}
return false;
}
@@ -292,7 +348,7 @@
mARContext.mWidth = getWidth();
mARContext.mHeight = getHeight();
mDocument.paint(mARContext, mTheme);
- if (mDebug) {
+ if (mDebug == 1) {
mCount++;
if (System.nanoTime() - mTime > 1000000000L) {
System.out.println(" count " + mCount + " fps");
diff --git a/core/res/res/values/stoppable_fgs_system_apps.xml b/core/res/res/values/stoppable_fgs_system_apps.xml
new file mode 100644
index 0000000..165ff61
--- /dev/null
+++ b/core/res/res/values/stoppable_fgs_system_apps.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (C) 2024 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.
+ */
+-->
+<resources>
+ <!-- A list of system apps whose FGS can be stopped in the task manager. -->
+ <string-array translatable="false" name="stoppable_fgs_system_apps">
+ </string-array>
+ <!-- stoppable_fgs_system_apps which is supposed to be overridden by vendor -->
+ <string-array translatable="false" name="vendor_stoppable_fgs_system_apps">
+ </string-array>
+</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index aa08d5e..db81a3b 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1306,6 +1306,8 @@
<java-symbol type="array" name="vendor_policy_exempt_apps" />
<java-symbol type="array" name="cloneable_apps" />
<java-symbol type="array" name="config_securityStatePackages" />
+ <java-symbol type="array" name="stoppable_fgs_system_apps" />
+ <java-symbol type="array" name="vendor_stoppable_fgs_system_apps" />
<java-symbol type="drawable" name="default_wallpaper" />
<java-symbol type="drawable" name="default_lock_wallpaper" />
diff --git a/core/tests/coretests/src/android/app/servertransaction/ClientTransactionListenerControllerTest.java b/core/tests/coretests/src/android/app/servertransaction/ClientTransactionListenerControllerTest.java
index 31a4f16..911b7ce 100644
--- a/core/tests/coretests/src/android/app/servertransaction/ClientTransactionListenerControllerTest.java
+++ b/core/tests/coretests/src/android/app/servertransaction/ClientTransactionListenerControllerTest.java
@@ -120,7 +120,8 @@
doReturn(newDisplayInfo).when(mIDisplayManager).getDisplayInfo(123);
mDisplayManager.registerDisplayListener(mListener, mHandler,
- DisplayManager.EVENT_FLAG_DISPLAY_CHANGED, null /* packageName */);
+ DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_CHANGED,
+ null /* packageName */);
mController.onDisplayChanged(123);
mHandler.runWithScissors(() -> { }, 0);
diff --git a/core/tests/coretests/src/android/hardware/display/DisplayManagerGlobalTest.java b/core/tests/coretests/src/android/hardware/display/DisplayManagerGlobalTest.java
index 5a0dacb..9552c88 100644
--- a/core/tests/coretests/src/android/hardware/display/DisplayManagerGlobalTest.java
+++ b/core/tests/coretests/src/android/hardware/display/DisplayManagerGlobalTest.java
@@ -55,9 +55,10 @@
@RunWith(AndroidJUnit4.class)
public class DisplayManagerGlobalTest {
- private static final long ALL_DISPLAY_EVENTS = DisplayManager.EVENT_FLAG_DISPLAY_ADDED
- | DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
- | DisplayManager.EVENT_FLAG_DISPLAY_REMOVED;
+ private static final long ALL_DISPLAY_EVENTS =
+ DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_ADDED
+ | DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_CHANGED
+ | DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_REMOVED;
@Mock
private IDisplayManager mDisplayManager;
@@ -127,19 +128,22 @@
int displayId = 1;
mDisplayManagerGlobal.registerDisplayListener(mListener, mHandler,
- ALL_DISPLAY_EVENTS & ~DisplayManager.EVENT_FLAG_DISPLAY_ADDED, null);
+ ALL_DISPLAY_EVENTS
+ & ~DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_ADDED, null);
callback.onDisplayEvent(displayId, DisplayManagerGlobal.EVENT_DISPLAY_ADDED);
waitForHandler();
Mockito.verifyZeroInteractions(mListener);
mDisplayManagerGlobal.registerDisplayListener(mListener, mHandler,
- ALL_DISPLAY_EVENTS & ~DisplayManager.EVENT_FLAG_DISPLAY_CHANGED, null);
+ ALL_DISPLAY_EVENTS
+ & ~DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_CHANGED, null);
callback.onDisplayEvent(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
waitForHandler();
Mockito.verifyZeroInteractions(mListener);
mDisplayManagerGlobal.registerDisplayListener(mListener, mHandler,
- ALL_DISPLAY_EVENTS & ~DisplayManager.EVENT_FLAG_DISPLAY_REMOVED, null);
+ ALL_DISPLAY_EVENTS
+ & ~DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_REMOVED, null);
callback.onDisplayEvent(displayId, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED);
waitForHandler();
Mockito.verifyZeroInteractions(mListener);
@@ -162,22 +166,25 @@
public void testDisplayManagerGlobalRegistersWithDisplayManager_WhenThereAreListeners()
throws RemoteException {
mDisplayManagerGlobal.registerDisplayListener(mListener, mHandler,
- DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS, null);
+ DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_BRIGHTNESS_CHANGED,
+ null);
InOrder inOrder = Mockito.inOrder(mDisplayManager);
inOrder.verify(mDisplayManager)
.registerCallbackWithEventMask(mCallbackCaptor.capture(),
- eq(DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS));
+ eq(DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_BRIGHTNESS_CHANGED));
mDisplayManagerGlobal.registerNativeChoreographerForRefreshRateCallbacks();
inOrder.verify(mDisplayManager)
.registerCallbackWithEventMask(mCallbackCaptor.capture(),
- eq(ALL_DISPLAY_EVENTS | DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS));
+ eq(ALL_DISPLAY_EVENTS
+ | DisplayManagerGlobal
+ .INTERNAL_EVENT_FLAG_DISPLAY_BRIGHTNESS_CHANGED));
mDisplayManagerGlobal.unregisterNativeChoreographerForRefreshRateCallbacks();
inOrder.verify(mDisplayManager)
.registerCallbackWithEventMask(mCallbackCaptor.capture(),
- eq(DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS));
+ eq(DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_BRIGHTNESS_CHANGED));
mDisplayManagerGlobal.unregisterDisplayListener(mListener);
inOrder.verify(mDisplayManager)
@@ -196,10 +203,12 @@
// One listener listens on add/remove, and the other one listens on change.
mDisplayManagerGlobal.registerDisplayListener(mListener, mHandler,
- DisplayManager.EVENT_FLAG_DISPLAY_ADDED
- | DisplayManager.EVENT_FLAG_DISPLAY_REMOVED, null /* packageName */);
+ DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_ADDED
+ | DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_REMOVED,
+ null /* packageName */);
mDisplayManagerGlobal.registerDisplayListener(mListener2, mHandler,
- DisplayManager.EVENT_FLAG_DISPLAY_CHANGED, null /* packageName */);
+ DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_CHANGED,
+ null /* packageName */);
mDisplayManagerGlobal.handleDisplayChangeFromWindowManager(321);
waitForHandler();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
index b9a3050..c92a278 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
@@ -21,6 +21,7 @@
import static android.view.RemoteAnimationTarget.MODE_OPENING;
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_CLOSE_PREPARE_BACK_NAVIGATION;
+import static android.window.BackEvent.EDGE_NONE;
import static android.window.TransitionInfo.FLAG_BACK_GESTURE_ANIMATED;
import static android.window.TransitionInfo.FLAG_IS_WALLPAPER;
import static android.window.TransitionInfo.FLAG_MOVED_TO_TOP;
@@ -533,7 +534,15 @@
if (keyAction == MotionEvent.ACTION_DOWN) {
if (!mBackGestureStarted) {
- mShouldStartOnNextMoveEvent = true;
+ if (swipeEdge == EDGE_NONE) {
+ // start animation immediately for non-gestural sources (without ACTION_MOVE
+ // events)
+ mThresholdCrossed = true;
+ onGestureStarted(touchX, touchY, swipeEdge);
+ mShouldStartOnNextMoveEvent = false;
+ } else {
+ mShouldStartOnNextMoveEvent = true;
+ }
}
} else if (keyAction == MotionEvent.ACTION_MOVE) {
if (!mBackGestureStarted && mShouldStartOnNextMoveEvent) {
@@ -1074,6 +1083,11 @@
mCurrentTracker.updateStartLocation();
BackMotionEvent startEvent = mCurrentTracker.createStartEvent(mApps[0]);
dispatchOnBackStarted(mActiveCallback, startEvent);
+ // TODO(b/373544911): onBackStarted is dispatched here so that
+ // WindowOnBackInvokedDispatcher knows about the back navigation and intercepts touch
+ // events while it's active. It would be cleaner and safer to disable multitouch
+ // altogether (same as in gesture-nav).
+ dispatchOnBackStarted(mBackNavigationInfo.getOnBackInvokedCallback(), startEvent);
}
}
diff --git a/nfc/java/android/nfc/INfcAdapter.aidl b/nfc/java/android/nfc/INfcAdapter.aidl
index 1346bd34..40fd068 100644
--- a/nfc/java/android/nfc/INfcAdapter.aidl
+++ b/nfc/java/android/nfc/INfcAdapter.aidl
@@ -119,4 +119,5 @@
boolean getSettingStatus();
boolean isTagPresent();
List<Entry> getRoutingTableEntryList();
+ void indicateDataMigration(boolean inProgress, String pkg);
}
diff --git a/nfc/java/android/nfc/NfcAdapter.java b/nfc/java/android/nfc/NfcAdapter.java
index d9fd42f..c5d8191 100644
--- a/nfc/java/android/nfc/NfcAdapter.java
+++ b/nfc/java/android/nfc/NfcAdapter.java
@@ -2795,11 +2795,8 @@
@IntRange(from = 0, to = 15) int gid, @IntRange(from = 0) int oid,
@NonNull byte[] payload) {
Objects.requireNonNull(payload, "Payload must not be null");
- try {
- return sService.sendVendorNciMessage(mt, gid, oid, payload);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return callServiceReturn(() -> sService.sendVendorNciMessage(mt, gid, oid, payload),
+ SEND_VENDOR_NCI_STATUS_FAILED);
}
/**
@@ -2873,6 +2870,18 @@
}
/**
+ * Used by data migration to indicate data migration is in progrerss or not.
+ *
+ * Note: This is @hide intentionally since the client is inside the NFC apex.
+ * @param inProgress true if migration is in progress, false once done.
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
+ public void indicateDataMigration(boolean inProgress) {
+ callService(() -> sService.indicateDataMigration(inProgress, mContext.getPackageName()));
+ }
+
+ /**
* Returns an instance of {@link NfcOemExtension} associated with {@link NfcAdapter} instance.
* @hide
*/
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InputRouteManager.java b/packages/SettingsLib/src/com/android/settingslib/media/InputRouteManager.java
index 4f315a2..76aa5bf 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/InputRouteManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/InputRouteManager.java
@@ -75,6 +75,24 @@
@Override
public void onAudioDevicesAdded(@NonNull AudioDeviceInfo[] addedDevices) {
applyDefaultSelectedTypeToAllPresets();
+
+ // Activate the last hot plugged valid input device, to match the output device
+ // behavior.
+ @AudioDeviceType int deviceTypeToActivate = mSelectedInputDeviceType;
+ for (AudioDeviceInfo info : addedDevices) {
+ if (InputMediaDevice.isSupportedInputDevice(info.getType())) {
+ deviceTypeToActivate = info.getType();
+ }
+ }
+
+ // Only activate if we find a different valid input device. e.g. if none of the
+ // addedDevices is supported input device, we don't need to activate anything.
+ if (mSelectedInputDeviceType != deviceTypeToActivate) {
+ mSelectedInputDeviceType = deviceTypeToActivate;
+ AudioDeviceAttributes deviceAttributes =
+ createInputDeviceAttributes(mSelectedInputDeviceType);
+ setPreferredDeviceForAllPresets(deviceAttributes);
+ }
}
@Override
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InputRouteManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InputRouteManagerTest.java
index 782cee2..d808a25 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InputRouteManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InputRouteManagerTest.java
@@ -24,6 +24,7 @@
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -138,6 +139,18 @@
/* address= */ "");
}
+ private AudioDeviceAttributes getUsbHeadsetDeviceAttributes() {
+ return new AudioDeviceAttributes(
+ AudioDeviceAttributes.ROLE_INPUT,
+ AudioDeviceInfo.TYPE_USB_HEADSET,
+ /* address= */ "");
+ }
+
+ private AudioDeviceAttributes getHdmiDeviceAttributes() {
+ return new AudioDeviceAttributes(
+ AudioDeviceAttributes.ROLE_INPUT, AudioDeviceInfo.TYPE_HDMI, /* address= */ "");
+ }
+
private void onPreferredDevicesForCapturePresetChanged(InputRouteManager inputRouteManager) {
final List<AudioDeviceAttributes> audioDeviceAttributesList =
new ArrayList<AudioDeviceAttributes>();
@@ -303,21 +316,47 @@
}
@Test
- public void onAudioDevicesAdded_shouldApplyDefaultSelectedDeviceToAllPresets() {
+ public void onAudioDevicesAdded_shouldActivateAddedDevice() {
final AudioManager audioManager = mock(AudioManager.class);
- AudioDeviceAttributes wiredHeadsetDeviceAttributes = getWiredHeadsetDeviceAttributes();
- when(audioManager.getDevicesForAttributes(INPUT_ATTRIBUTES))
- .thenReturn(Collections.singletonList(wiredHeadsetDeviceAttributes));
-
InputRouteManager inputRouteManager = new InputRouteManager(mContext, audioManager);
AudioDeviceInfo[] devices = {mockWiredHeadsetInfo()};
inputRouteManager.mAudioDeviceCallback.onAudioDevicesAdded(devices);
- // Called twice, one after initiation, the other after onAudioDevicesAdded call.
- verify(audioManager, atLeast(2)).getDevicesForAttributes(INPUT_ATTRIBUTES);
+ // The only added wired headset will be activated.
for (@MediaRecorder.Source int preset : PRESETS) {
- verify(audioManager, atLeast(2))
- .setPreferredDeviceForCapturePreset(preset, wiredHeadsetDeviceAttributes);
+ verify(audioManager, atLeast(1))
+ .setPreferredDeviceForCapturePreset(preset, getWiredHeadsetDeviceAttributes());
+ }
+ }
+
+ @Test
+ public void onAudioDevicesAdded_shouldActivateLastAddedDevice() {
+ final AudioManager audioManager = mock(AudioManager.class);
+ InputRouteManager inputRouteManager = new InputRouteManager(mContext, audioManager);
+ AudioDeviceInfo[] devices = {mockWiredHeadsetInfo(), mockUsbHeadsetInfo()};
+ inputRouteManager.mAudioDeviceCallback.onAudioDevicesAdded(devices);
+
+ // When adding multiple valid input devices, the last added device (usb headset in this
+ // case) will be activated.
+ for (@MediaRecorder.Source int preset : PRESETS) {
+ verify(audioManager, never())
+ .setPreferredDeviceForCapturePreset(preset, getWiredHeadsetDeviceAttributes());
+ verify(audioManager, atLeast(1))
+ .setPreferredDeviceForCapturePreset(preset, getUsbHeadsetDeviceAttributes());
+ }
+ }
+
+ @Test
+ public void onAudioDevicesAdded_doNotActivateInvalidAddedDevice() {
+ final AudioManager audioManager = mock(AudioManager.class);
+ InputRouteManager inputRouteManager = new InputRouteManager(mContext, audioManager);
+ AudioDeviceInfo[] devices = {mockHdmiInfo()};
+ inputRouteManager.mAudioDeviceCallback.onAudioDevicesAdded(devices);
+
+ // Do not activate since HDMI is not a valid input device.
+ for (@MediaRecorder.Source int preset : PRESETS) {
+ verify(audioManager, never())
+ .setPreferredDeviceForCapturePreset(preset, getHdmiDeviceAttributes());
}
}
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/TEST_MAPPING b/packages/SystemUI/accessibility/accessibilitymenu/TEST_MAPPING
index 1820f39..1903d22 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/TEST_MAPPING
+++ b/packages/SystemUI/accessibility/accessibilitymenu/TEST_MAPPING
@@ -1,8 +1,7 @@
{
- // TODO: b/324945360 - Re-enable on presubmit after fixing failures
"postsubmit": [
{
"name": "AccessibilityMenuServiceTests"
}
]
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/aconfig/accessibility.aconfig b/packages/SystemUI/aconfig/accessibility.aconfig
index 5251246..b5eba08 100644
--- a/packages/SystemUI/aconfig/accessibility.aconfig
+++ b/packages/SystemUI/aconfig/accessibility.aconfig
@@ -118,3 +118,10 @@
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ name: "floating_menu_hearing_device_status_icon"
+ namespace: "accessibility"
+ description: "Update hearing device icon in floating menu according to the connection status."
+ bug: "357882387"
+}
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index 3bf3e24..87ea2a7 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -1743,3 +1743,13 @@
description: "An implementation of shortcut customizations through shortcut helper."
bug: "365064144"
}
+
+flag {
+ name: "stoppable_fgs_system_app"
+ namespace: "systemui"
+ description: "System app with foreground service can opt in to be stoppable."
+ bug: "376564917"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/statusbar/phone/SystemUIDialogFactoryExt.kt b/packages/SystemUI/compose/features/src/com/android/systemui/statusbar/phone/SystemUIDialogFactoryExt.kt
index e9b7335..d58e1bf 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/statusbar/phone/SystemUIDialogFactoryExt.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/statusbar/phone/SystemUIDialogFactoryExt.kt
@@ -98,19 +98,20 @@
theme: Int = SystemUIDialog.DEFAULT_THEME,
dismissOnDeviceLock: Boolean = SystemUIDialog.DEFAULT_DISMISS_ON_DEVICE_LOCK,
@GravityInt dialogGravity: Int? = null,
+ dialogDelegate: DialogDelegate<SystemUIDialog> =
+ object : DialogDelegate<SystemUIDialog> {
+ override fun onCreate(dialog: SystemUIDialog, savedInstanceState: Bundle?) {
+ super.onCreate(dialog, savedInstanceState)
+ dialogGravity?.let { dialog.window?.setGravity(it) }
+ }
+ },
content: @Composable (SystemUIDialog) -> Unit,
): ComponentSystemUIDialog {
return create(
context = context,
theme = theme,
dismissOnDeviceLock = dismissOnDeviceLock,
- delegate =
- object : DialogDelegate<SystemUIDialog> {
- override fun onCreate(dialog: SystemUIDialog, savedInstanceState: Bundle?) {
- super.onCreate(dialog, savedInstanceState)
- dialogGravity?.let { dialog.window?.setGravity(it) }
- }
- },
+ delegate = dialogDelegate,
content = content,
)
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/brightness/data/repository/ScreenBrightnessDisplayManagerRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/brightness/data/repository/ScreenBrightnessDisplayManagerRepositoryTest.kt
index 0983105..f4cffc5 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/brightness/data/repository/ScreenBrightnessDisplayManagerRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/brightness/data/repository/ScreenBrightnessDisplayManagerRepositoryTest.kt
@@ -20,7 +20,7 @@
import android.hardware.display.BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE
import android.hardware.display.BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF
import android.hardware.display.DisplayManager
-import android.hardware.display.DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS
+import android.hardware.display.DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS
import android.view.Display
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
@@ -119,7 +119,8 @@
.registerDisplayListener(
capture(listenerCaptor),
eq(null),
- eq(EVENT_FLAG_DISPLAY_BRIGHTNESS),
+ eq(0),
+ eq(PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS),
)
val newBrightness = BrightnessInfo(0.6f, 0.3f, 0.9f)
@@ -157,7 +158,8 @@
.registerDisplayListener(
capture(listenerCaptor),
eq(null),
- eq(EVENT_FLAG_DISPLAY_BRIGHTNESS),
+ eq(0),
+ eq(PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS),
)
changeBrightnessInfoAndNotify(
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/display/data/repository/DisplayRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/display/data/repository/DisplayRepositoryTest.kt
index cd8b2e1..e6e5665 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/display/data/repository/DisplayRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/display/data/repository/DisplayRepositoryTest.kt
@@ -540,7 +540,8 @@
.registerDisplayListener(
connectedDisplayListener.capture(),
eq(testHandler),
- eq(DisplayManager.EVENT_FLAG_DISPLAY_CONNECTION_CHANGED),
+ eq(0),
+ eq(DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_CONNECTION_CHANGED),
)
return flowValue
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/ui/ShortcutHelperDialogStarterTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/ui/ShortcutHelperDialogStarterTest.kt
index d1431ee..1580ea5 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/ui/ShortcutHelperDialogStarterTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/ui/ShortcutHelperDialogStarterTest.kt
@@ -22,6 +22,7 @@
import com.android.systemui.SysuiTestCase
import com.android.systemui.keyboard.shortcut.data.source.FakeKeyboardShortcutGroupsSource
import com.android.systemui.keyboard.shortcut.data.source.TestShortcuts
+import com.android.systemui.keyboard.shortcut.shortcutCustomizationDialogStarterFactory
import com.android.systemui.keyboard.shortcut.shortcutHelperAppCategoriesShortcutsSource
import com.android.systemui.keyboard.shortcut.shortcutHelperCurrentAppShortcutsSource
import com.android.systemui.keyboard.shortcut.shortcutHelperInputShortcutsSource
@@ -71,7 +72,13 @@
private val starter: ShortcutHelperDialogStarter =
with(kosmos) {
- ShortcutHelperDialogStarter(coroutineScope, viewModel, dialogFactory, activityStarter)
+ ShortcutHelperDialogStarter(
+ coroutineScope,
+ viewModel,
+ shortcutCustomizationDialogStarterFactory,
+ dialogFactory,
+ activityStarter,
+ )
}
@Before
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/FgsManagerControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/FgsManagerControllerTest.java
index 16ae466..0356422 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/FgsManagerControllerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/FgsManagerControllerTest.java
@@ -42,6 +42,7 @@
import android.os.Binder;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.platform.test.annotations.EnableFlags;
import android.provider.DeviceConfig;
import android.testing.TestableLooper;
@@ -49,6 +50,7 @@
import androidx.test.filters.SmallTest;
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
+import com.android.systemui.Flags;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.animation.DialogTransitionAnimator;
import com.android.systemui.broadcast.BroadcastDispatcher;
@@ -315,13 +317,36 @@
}
@Test
+ @EnableFlags(Flags.FLAG_STOPPABLE_FGS_SYSTEM_APP)
+ public void testButtonVisibilityOfStoppableApps() throws Exception {
+ setUserProfiles(0);
+ setBackgroundRestrictionExemptionReason("pkg", 12345, REASON_ALLOWLISTED_PACKAGE);
+ setBackgroundRestrictionExemptionReason("vendor_pkg", 67890, REASON_ALLOWLISTED_PACKAGE);
+
+ // Same as above, but apps are opt-in to be stoppable
+ setStoppableApps(new String[] {"pkg"}, /* vendor */ false);
+ setStoppableApps(new String[] {"vendor_pkg"}, /* vendor */ true);
+
+ final Binder binder = new Binder();
+ setShowStopButtonForUserAllowlistedApps(true);
+ // Both are foreground.
+ mIForegroundServiceObserver.onForegroundStateChanged(binder, "pkg", 0, true);
+ mIForegroundServiceObserver.onForegroundStateChanged(binder, "vendor_pkg", 0, true);
+ Assert.assertEquals(2, mFmc.visibleButtonsCount());
+
+ // The vendor package is no longer foreground. Only `pkg` remains.
+ mIForegroundServiceObserver.onForegroundStateChanged(binder, "vendor_pkg", 0, false);
+ Assert.assertEquals(1, mFmc.visibleButtonsCount());
+ }
+
+ @Test
public void testShowUserVisibleJobsOnCreation() {
// Test when the default is on.
mDeviceConfigProxyFake.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
SystemUiDeviceConfigFlags.TASK_MANAGER_SHOW_USER_VISIBLE_JOBS,
"true", false);
FgsManagerController fmc = new FgsManagerControllerImpl(
- mContext,
+ mContext.getResources(),
mMainExecutor,
mBackgroundExecutor,
mSystemClock,
@@ -348,7 +373,7 @@
SystemUiDeviceConfigFlags.TASK_MANAGER_SHOW_USER_VISIBLE_JOBS,
"false", false);
fmc = new FgsManagerControllerImpl(
- mContext,
+ mContext.getResources(),
mMainExecutor,
mBackgroundExecutor,
mSystemClock,
@@ -446,6 +471,11 @@
.getBackgroundRestrictionExemptionReason(uid);
}
+ private void setStoppableApps(String[] packageNames, boolean vendor) throws Exception {
+ overrideResource(vendor ? com.android.internal.R.array.vendor_stoppable_fgs_system_apps
+ : com.android.internal.R.array.stoppable_fgs_system_apps, packageNames);
+ }
+
FgsManagerController createFgsManagerController() throws RemoteException {
ArgumentCaptor<IForegroundServiceObserver> iForegroundServiceObserverArgumentCaptor =
ArgumentCaptor.forClass(IForegroundServiceObserver.class);
@@ -455,7 +485,7 @@
ArgumentCaptor.forClass(BroadcastReceiver.class);
FgsManagerController result = new FgsManagerControllerImpl(
- mContext,
+ mContext.getResources(),
mMainExecutor,
mBackgroundExecutor,
mSystemClock,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModelTest.kt
index 740abf3..76390fd 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModelTest.kt
@@ -18,12 +18,13 @@
import android.content.res.mainResources
import android.platform.test.annotations.DisableFlags
-import androidx.test.ext.junit.runners.AndroidJUnit4
+import android.platform.test.flag.junit.FlagsParameterization
import androidx.test.filters.SmallTest
import com.android.systemui.Flags.FLAG_KEYGUARD_WM_STATE_REFACTOR
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.flags.Flags
+import com.android.systemui.flags.andSceneContainer
import com.android.systemui.flags.fakeFeatureFlagsClassic
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
@@ -51,17 +52,20 @@
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4
+import platform.test.runner.parameterized.Parameters
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RunWith(AndroidJUnit4::class)
-class NotificationIconContainerAlwaysOnDisplayViewModelTest : SysuiTestCase() {
+@RunWith(ParameterizedAndroidJunit4::class)
+class NotificationIconContainerAlwaysOnDisplayViewModelTest(flags: FlagsParameterization) :
+ SysuiTestCase() {
private val kosmos =
testKosmos().apply {
fakeFeatureFlagsClassic.apply { set(Flags.FULL_SCREEN_USER_SWITCHER, value = false) }
}
- val underTest =
+ val underTest by lazy {
NotificationIconContainerAlwaysOnDisplayViewModel(
kosmos.testDispatcher,
kosmos.alwaysOnDisplayNotificationIconsInteractor,
@@ -70,11 +74,24 @@
kosmos.mainResources,
kosmos.shadeInteractor,
)
+ }
val testScope = kosmos.testScope
val keyguardRepository = kosmos.fakeKeyguardRepository
val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository
val powerRepository = kosmos.fakePowerRepository
+ companion object {
+ @JvmStatic
+ @Parameters(name = "{0}")
+ fun getParams(): List<FlagsParameterization> {
+ return FlagsParameterization.allCombinationsOf().andSceneContainer()
+ }
+ }
+
+ init {
+ mSetFlagsRule.setFlagsParameterization(flags)
+ }
+
@Before
fun setup() {
keyguardRepository.setKeyguardShowing(true)
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 5a8417d..d30f73f 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -3743,6 +3743,11 @@
is a component that shows the user which keyboard shortcuts they can use.
[CHAR LIMIT=NONE] -->
<string name="shortcut_helper_customize_mode_title">Customize keyboard shortcuts</string>
+ <!-- Sub title at the top of the keyboard shortcut helper customization dialog. Explains to the
+ user what action they need to take in the customization dialog to assign a new custom shortcut.
+ The helper is a component that shows the user which keyboard shortcuts they can use.
+ [CHAR LIMIT=NONE] -->
+ <string name="shortcut_helper_customize_mode_sub_title">Press key to assign shortcut</string>
<!-- Placeholder text shown in the search box of the keyboard shortcut helper, when the user
hasn't typed in anything in the search box yet. The helper is a component that shows the
user which keyboard shortcuts they can use. [CHAR LIMIT=NONE] -->
@@ -3754,6 +3759,16 @@
use. The helper shows shortcuts in categories, which can be collapsed or expanded.
[CHAR LIMIT=NONE] -->
<string name="shortcut_helper_content_description_collapse_icon">Collapse icon</string>
+ <!-- Content description of the Meta key (also called Action Key) icon that prompts users to
+ press some key combination starting with meta key to assign new key combination to shortcut
+ in shortcut helper customization dialog. The helper is a component that shows the user
+ which keyboard shortcuts they can use. [CHAR LIMIT=NONE] -->
+ <string name="shortcut_helper_content_description_meta_key">Action or Meta key icon</string>
+ <!-- Content description of the plus icon after the meta key icon prompts users to
+ press some key combination starting with meta key to assign new key combination to shortcut
+ in shortcut helper customization dialog. The helper is a component that shows the user
+ which keyboard shortcuts they can use. [CHAR LIMIT=NONE] -->
+ <string name="shortcut_helper_content_description_plus_icon">Plus icon</string>
<!-- Description text of the button that allows user to customize shortcuts in keyboard
shortcut helper The helper is a component that shows the user which keyboard shortcuts
they can use. [CHAR LIMIT=NONE] -->
@@ -3784,6 +3799,24 @@
open keyboard settings while in shortcut helper. The helper is a component that shows the
user which keyboard shortcuts they can use. [CHAR LIMIT=NONE] -->
<string name="shortcut_helper_keyboard_settings_buttons_label">Keyboard Settings</string>
+ <!-- Label on the set shortcut button in keyboard shortcut helper customize dialog, that allows user to
+ confirm and assign key combination to selected shortcut. The helper is a component that
+ shows the user which keyboard shortcuts they can use. [CHAR LIMIT=NONE] -->
+ <string name="shortcut_helper_customize_dialog_set_shortcut_button_label">Set shortcut</string>
+ <!-- Label on the cancel button in keyboard shortcut helper customize dialog, that allows user to
+ cancel and exit shortcut customization dialog, returning to the main shortcut helper page.
+ The helper is a component that shows the user which keyboard shortcuts they can use.
+ [CHAR LIMIT=NONE] -->
+ <string name="shortcut_helper_customize_dialog_cancel_button_label">Cancel</string>
+ <!-- Placeholder text, prompting user to Press key combination assign to shortcut. This is shown
+ in shortcut helper's "Add Custom Shortcut" Dialog text field when user hasn't pressed
+ any key yet. The helper is a component that shows the user which keyboard shortcuts
+ they can use. [CHAR LIMIT=NONE] -->
+ <string name="shortcut_helper_add_shortcut_dialog_placeholder">Press key</string>
+ <!-- Error message displayed when the user select a key combination that is already in use while
+ assigning a new custom key combination to a shortcut in shortcut helper. The helper is a
+ component that shows the user which keyboard shortcuts they can use. [CHAR LIMIT=NONE] -->
+ <string name="shortcut_helper_customize_dialog_error_message">Key combination already in use. Try another key.</string>
<!-- Keyboard touchpad tutorial scheduler-->
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
index 6209ed8..e332280 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
@@ -21,6 +21,7 @@
import android.graphics.Rect;
import android.os.Bundle;
import android.os.UserHandle;
+import android.view.KeyEvent;
import android.view.MotionEvent;
import com.android.internal.util.ScreenshotRequest;
@@ -102,9 +103,9 @@
oneway void expandNotificationPanel() = 29;
/**
- * Notifies SystemUI to invoke Back.
+ * Notifies SystemUI of a back KeyEvent.
*/
- oneway void onBackPressed() = 44;
+ oneway void onBackEvent(in KeyEvent keyEvent) = 44;
/** Sets home rotation enabled. */
oneway void setHomeRotationEnabled(boolean enabled) = 45;
diff --git a/packages/SystemUI/src/com/android/systemui/brightness/data/repository/ScreenBrightnessRepository.kt b/packages/SystemUI/src/com/android/systemui/brightness/data/repository/ScreenBrightnessRepository.kt
index 06d3917..3270c71 100644
--- a/packages/SystemUI/src/com/android/systemui/brightness/data/repository/ScreenBrightnessRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/brightness/data/repository/ScreenBrightnessRepository.kt
@@ -19,6 +19,7 @@
import android.annotation.SuppressLint
import android.hardware.display.BrightnessInfo
import android.hardware.display.DisplayManager
+import com.android.app.tracing.coroutines.launchTraced as launch
import com.android.systemui.brightness.shared.model.BrightnessLog
import com.android.systemui.brightness.shared.model.LinearBrightness
import com.android.systemui.brightness.shared.model.formatBrightness
@@ -46,7 +47,6 @@
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.stateIn
-import com.android.app.tracing.coroutines.launchTraced as launch
import kotlinx.coroutines.withContext
/**
@@ -90,10 +90,7 @@
@Background private val backgroundContext: CoroutineContext,
) : ScreenBrightnessRepository {
- private val apiQueue =
- Channel<SetBrightnessMethod>(
- capacity = UNLIMITED,
- )
+ private val apiQueue = Channel<SetBrightnessMethod>(capacity = UNLIMITED)
init {
applicationScope.launch(context = backgroundContext) {
@@ -132,7 +129,8 @@
displayManager.registerDisplayListener(
listener,
null,
- DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS,
+ /* eventFlags */ 0,
+ DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS,
)
awaitClose { displayManager.unregisterDisplayListener(listener) }
@@ -190,8 +188,10 @@
private sealed interface SetBrightnessMethod {
val value: LinearBrightness
+
@JvmInline
value class Temporary(override val value: LinearBrightness) : SetBrightnessMethod
+
@JvmInline
value class Permanent(override val value: LinearBrightness) : SetBrightnessMethod
}
@@ -201,7 +201,7 @@
LOG_BUFFER_BRIGHTNESS_CHANGE_TAG,
if (permanent) LogLevel.DEBUG else LogLevel.VERBOSE,
{ str1 = value.formatBrightness() },
- { "Change requested: $str1" }
+ { "Change requested: $str1" },
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/display/data/repository/DisplayRepository.kt b/packages/SystemUI/src/com/android/systemui/display/data/repository/DisplayRepository.kt
index 034cb31..1fa829a 100644
--- a/packages/SystemUI/src/com/android/systemui/display/data/repository/DisplayRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/display/data/repository/DisplayRepository.kt
@@ -264,7 +264,8 @@
displayManager.registerDisplayListener(
callback,
backgroundHandler,
- DisplayManager.EVENT_FLAG_DISPLAY_CONNECTION_CHANGED,
+ /* eventFlags */ 0,
+ DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_CONNECTION_CHANGED,
)
awaitClose { displayManager.unregisterDisplayListener(callback) }
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/domain/interactor/ShortcutCustomizationInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/domain/interactor/ShortcutCustomizationInteractor.kt
new file mode 100644
index 0000000..85d2214
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/domain/interactor/ShortcutCustomizationInteractor.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyboard.shortcut.domain.interactor
+
+import android.view.KeyEvent.META_META_ON
+import com.android.systemui.keyboard.shortcut.data.repository.ShortcutHelperKeys
+import com.android.systemui.keyboard.shortcut.shared.model.ShortcutKey
+import javax.inject.Inject
+
+class ShortcutCustomizationInteractor @Inject constructor() {
+ fun getDefaultCustomShortcutModifierKey(): ShortcutKey.Icon.ResIdIcon {
+ return ShortcutKey.Icon.ResIdIcon(ShortcutHelperKeys.keyIcons[META_META_ON]!!)
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/shared/model/ShortcutInfo.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/shared/model/ShortcutInfo.kt
new file mode 100644
index 0000000..e4ccc2c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/shared/model/ShortcutInfo.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyboard.shortcut.shared.model
+
+data class ShortcutInfo(
+ val label: String,
+ val categoryType: ShortcutCategoryType,
+ val subCategoryLabel: String,
+)
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/ShortcutCustomizationDialogDelegate.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/ShortcutCustomizationDialogDelegate.kt
new file mode 100644
index 0000000..c98472e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/ShortcutCustomizationDialogDelegate.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyboard.shortcut.ui
+
+import android.os.Bundle
+import android.view.Gravity
+import android.view.WindowManager
+import com.android.systemui.statusbar.phone.DialogDelegate
+import com.android.systemui.statusbar.phone.SystemUIDialog
+
+class ShortcutCustomizationDialogDelegate : DialogDelegate<SystemUIDialog> {
+
+ override fun onCreate(dialog: SystemUIDialog, savedInstanceState: Bundle?) {
+ super.onCreate(dialog, savedInstanceState)
+ dialog.window?.apply { setGravity(Gravity.CENTER) }
+ }
+
+ override fun getWidth(dialog: SystemUIDialog): Int {
+ return WindowManager.LayoutParams.WRAP_CONTENT
+ }
+
+ override fun getHeight(dialog: SystemUIDialog): Int {
+ return WindowManager.LayoutParams.WRAP_CONTENT
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/ShortcutCustomizationDialogStarter.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/ShortcutCustomizationDialogStarter.kt
new file mode 100644
index 0000000..02e206e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/ShortcutCustomizationDialogStarter.kt
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyboard.shortcut.ui
+
+import android.app.Dialog
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.layout.wrapContentHeight
+import androidx.compose.runtime.getValue
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.unit.dp
+import androidx.lifecycle.compose.collectAsStateWithLifecycle
+import com.android.systemui.keyboard.shortcut.shared.model.ShortcutInfo
+import com.android.systemui.keyboard.shortcut.ui.composable.AssignNewShortcutDialog
+import com.android.systemui.keyboard.shortcut.ui.model.ShortcutCustomizationUiState
+import com.android.systemui.keyboard.shortcut.ui.viewmodel.ShortcutCustomizationViewModel
+import com.android.systemui.lifecycle.ExclusiveActivatable
+import com.android.systemui.statusbar.phone.SystemUIDialogFactory
+import com.android.systemui.statusbar.phone.create
+import dagger.assisted.AssistedFactory
+import dagger.assisted.AssistedInject
+
+class ShortcutCustomizationDialogStarter
+@AssistedInject
+constructor(
+ viewModelFactory: ShortcutCustomizationViewModel.Factory,
+ private val dialogFactory: SystemUIDialogFactory,
+) : ExclusiveActivatable() {
+
+ private var dialog: Dialog? = null
+ private val viewModel = viewModelFactory.create()
+
+ override suspend fun onActivated(): Nothing {
+ viewModel.shortcutCustomizationUiState.collect { uiState ->
+ if (
+ uiState is ShortcutCustomizationUiState.AddShortcutDialog &&
+ !uiState.isDialogShowing
+ ) {
+ dialog = createAddShortcutDialog().also { it.show() }
+ viewModel.onAddShortcutDialogShown()
+ } else if (uiState is ShortcutCustomizationUiState.Inactive) {
+ dialog?.dismiss()
+ dialog = null
+ }
+ }
+ }
+
+ fun onAddShortcutDialogRequested(shortcutBeingCustomized: ShortcutInfo) {
+ viewModel.onAddShortcutDialogRequested(shortcutBeingCustomized)
+ }
+
+ private fun createAddShortcutDialog(): Dialog {
+ return dialogFactory.create(dialogDelegate = ShortcutCustomizationDialogDelegate()) { dialog
+ ->
+ val uiState by viewModel.shortcutCustomizationUiState.collectAsStateWithLifecycle()
+ AssignNewShortcutDialog(
+ uiState = uiState,
+ modifier = Modifier.width(364.dp).wrapContentHeight().padding(vertical = 24.dp),
+ onKeyPress = { viewModel.onKeyPressed(it) },
+ onCancel = { dialog.dismiss() },
+ )
+ dialog.setOnDismissListener { viewModel.onAddShortcutDialogDismissed() }
+ }
+ }
+
+ @AssistedFactory
+ interface Factory {
+ fun create(): ShortcutCustomizationDialogStarter
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/ShortcutHelperDialogStarter.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/ShortcutHelperDialogStarter.kt
index d33ab2a..807c70b 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/ShortcutHelperDialogStarter.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/ShortcutHelperDialogStarter.kt
@@ -24,6 +24,7 @@
import android.provider.Settings
import androidx.annotation.VisibleForTesting
import androidx.compose.foundation.layout.width
+import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.lifecycle.compose.collectAsStateWithLifecycle
@@ -47,15 +48,18 @@
@Inject
constructor(
@Application private val applicationScope: CoroutineScope,
- private val viewModel: ShortcutHelperViewModel,
+ private val shortcutHelperViewModel: ShortcutHelperViewModel,
+ shortcutCustomizationDialogStarterFactory: ShortcutCustomizationDialogStarter.Factory,
private val dialogFactory: SystemUIDialogFactory,
private val activityStarter: ActivityStarter,
) : CoreStartable {
@VisibleForTesting var dialog: Dialog? = null
+ private val shortcutCustomizationDialogStarter =
+ shortcutCustomizationDialogStarterFactory.create()
override fun start() {
- viewModel.shouldShow
+ shortcutHelperViewModel.shouldShow
.map { shouldShow ->
if (shouldShow) {
dialog = createShortcutHelperDialog().also { it.show() }
@@ -69,16 +73,21 @@
private fun createShortcutHelperDialog(): Dialog {
return dialogFactory.createBottomSheet(
content = { dialog ->
- val shortcutsUiState by viewModel.shortcutsUiState.collectAsStateWithLifecycle()
+ val shortcutsUiState by
+ shortcutHelperViewModel.shortcutsUiState.collectAsStateWithLifecycle()
+ LaunchedEffect(Unit) { shortcutCustomizationDialogStarter.activate() }
ShortcutHelper(
modifier = Modifier.width(getWidth()),
shortcutsUiState = shortcutsUiState,
onKeyboardSettingsClicked = { onKeyboardSettingsClicked(dialog) },
- onSearchQueryChanged = { viewModel.onSearchQueryChanged(it) },
+ onSearchQueryChanged = { shortcutHelperViewModel.onSearchQueryChanged(it) },
+ onCustomizationRequested = {
+ shortcutCustomizationDialogStarter.onAddShortcutDialogRequested(it)
+ },
)
- dialog.setOnDismissListener { viewModel.onViewClosed() }
+ dialog.setOnDismissListener { shortcutHelperViewModel.onViewClosed() }
},
- maxWidth = ShortcutHelperBottomSheet.LargeScreenWidthLandscape
+ maxWidth = ShortcutHelperBottomSheet.LargeScreenWidthLandscape,
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutCustomizer.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutCustomizer.kt
new file mode 100644
index 0000000..43f0f20
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutCustomizer.kt
@@ -0,0 +1,272 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyboard.shortcut.ui.composable
+
+import androidx.compose.foundation.background
+import androidx.compose.foundation.border
+import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.foundation.interaction.collectIsFocusedAsState
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.sizeIn
+import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.layout.wrapContentSize
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.Add
+import androidx.compose.material.icons.filled.ErrorOutline
+import androidx.compose.material3.Icon
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.input.key.KeyEvent
+import androidx.compose.ui.input.key.onPreviewKeyEvent
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import com.android.systemui.keyboard.shortcut.shared.model.ShortcutKey
+import com.android.systemui.keyboard.shortcut.ui.model.ShortcutCustomizationUiState
+import com.android.systemui.res.R
+
+@Composable
+fun AssignNewShortcutDialog(
+ uiState: ShortcutCustomizationUiState,
+ modifier: Modifier = Modifier,
+ onKeyPress: (KeyEvent) -> Boolean,
+ onCancel: () -> Unit,
+) {
+ if (uiState is ShortcutCustomizationUiState.AddShortcutDialog) {
+ Column(modifier = modifier) {
+ Title(
+ uiState.shortcutLabel,
+ modifier = Modifier.padding(horizontal = 24.dp).width(316.dp),
+ )
+ Description(
+ modifier = Modifier.padding(top = 24.dp, start = 24.dp, end = 24.dp).width(316.dp)
+ )
+ PromptShortcutModifier(
+ modifier =
+ Modifier.padding(top = 24.dp, start = 116.5.dp, end = 116.5.dp)
+ .width(131.dp)
+ .height(48.dp),
+ defaultModifierKey = uiState.defaultCustomShortcutModifierKey,
+ )
+ SelectedKeyCombinationContainer(
+ shouldShowErrorMessage = uiState.shouldShowErrorMessage,
+ onKeyPress = onKeyPress,
+ )
+ KeyCombinationAlreadyInUseErrorMessage(uiState.shouldShowErrorMessage)
+ DialogButtons(onCancel, isValidKeyCombination = uiState.isValidKeyCombination)
+ }
+ }
+}
+
+@Composable
+fun DialogButtons(onCancel: () -> Unit, isValidKeyCombination: Boolean) {
+ Row(
+ modifier =
+ Modifier.padding(top = 24.dp, start = 24.dp, end = 24.dp)
+ .sizeIn(minWidth = 316.dp, minHeight = 48.dp),
+ verticalAlignment = Alignment.Bottom,
+ horizontalArrangement = Arrangement.End,
+ ) {
+ ShortcutHelperButton(
+ shape = RoundedCornerShape(50.dp),
+ onClick = onCancel,
+ color = Color.Transparent,
+ width = 80.dp,
+ contentColor = MaterialTheme.colorScheme.primary,
+ text = stringResource(R.string.shortcut_helper_customize_dialog_cancel_button_label),
+ )
+ Spacer(modifier = Modifier.width(8.dp))
+ ShortcutHelperButton(
+ onClick = {},
+ color = MaterialTheme.colorScheme.primary,
+ width = 116.dp,
+ contentColor = MaterialTheme.colorScheme.onPrimary,
+ text =
+ stringResource(R.string.shortcut_helper_customize_dialog_set_shortcut_button_label),
+ enabled = isValidKeyCombination,
+ )
+ }
+}
+
+@Composable
+fun KeyCombinationAlreadyInUseErrorMessage(shouldShowErrorMessage: Boolean) {
+ if (shouldShowErrorMessage) {
+ Box(modifier = Modifier.padding(horizontal = 16.dp).width(332.dp).height(40.dp)) {
+ Text(
+ text = stringResource(R.string.shortcut_helper_customize_dialog_error_message),
+ style = MaterialTheme.typography.bodyMedium,
+ fontSize = 14.sp,
+ lineHeight = 20.sp,
+ fontWeight = FontWeight.W500,
+ color = MaterialTheme.colorScheme.error,
+ modifier = Modifier.padding(start = 24.dp).width(252.dp),
+ )
+ }
+ }
+}
+
+@Composable
+fun SelectedKeyCombinationContainer(
+ keyCombination: String =
+ stringResource(R.string.shortcut_helper_add_shortcut_dialog_placeholder),
+ shouldShowErrorMessage: Boolean,
+ onKeyPress: (KeyEvent) -> Boolean,
+) {
+ val interactionSource = remember { MutableInteractionSource() }
+ val isFocused by interactionSource.collectIsFocusedAsState()
+ val outlineColor =
+ if (!isFocused) MaterialTheme.colorScheme.outline
+ else if (shouldShowErrorMessage) MaterialTheme.colorScheme.error
+ else MaterialTheme.colorScheme.primary
+
+ ClickableShortcutSurface(
+ onClick = {},
+ color = Color.Transparent,
+ shape = RoundedCornerShape(50.dp),
+ modifier =
+ Modifier.padding(all = 16.dp)
+ .sizeIn(minWidth = 332.dp, minHeight = 56.dp)
+ .border(width = 2.dp, color = outlineColor, shape = RoundedCornerShape(50.dp))
+ .onPreviewKeyEvent { onKeyPress(it) },
+ interactionSource = interactionSource,
+ ) {
+ Row(
+ modifier = Modifier.padding(start = 24.dp, top = 16.dp, end = 16.dp, bottom = 16.dp),
+ verticalAlignment = Alignment.CenterVertically,
+ ) {
+ Text(
+ text = keyCombination,
+ style = MaterialTheme.typography.headlineSmall,
+ fontSize = 16.sp,
+ lineHeight = 24.sp,
+ fontWeight = FontWeight.W500,
+ color = MaterialTheme.colorScheme.onSurfaceVariant,
+ modifier = Modifier.width(252.dp),
+ )
+ Spacer(modifier = Modifier.weight(1f))
+ if (shouldShowErrorMessage) {
+ Icon(
+ imageVector = Icons.Default.ErrorOutline,
+ contentDescription = null,
+ modifier = Modifier.size(20.dp),
+ tint = MaterialTheme.colorScheme.error,
+ )
+ }
+ }
+ }
+}
+
+@Composable
+private fun Title(title: String, modifier: Modifier = Modifier) {
+ Text(
+ text = title,
+ style = MaterialTheme.typography.headlineSmall,
+ fontSize = 24.sp,
+ modifier = modifier.wrapContentSize(Alignment.Center),
+ color = MaterialTheme.colorScheme.onSurface,
+ lineHeight = 32.sp,
+ )
+}
+
+@Composable
+private fun Description(modifier: Modifier = Modifier) {
+ Text(
+ text = stringResource(id = R.string.shortcut_helper_customize_mode_sub_title),
+ style = MaterialTheme.typography.bodyMedium,
+ fontSize = 14.sp,
+ lineHeight = 20.sp,
+ modifier = modifier.wrapContentSize(Alignment.Center),
+ color = MaterialTheme.colorScheme.onSurfaceVariant,
+ )
+}
+
+@Composable
+private fun PromptShortcutModifier(
+ modifier: Modifier,
+ defaultModifierKey: ShortcutKey.Icon.ResIdIcon,
+) {
+ Row(modifier = modifier, horizontalArrangement = Arrangement.spacedBy(2.dp)) {
+ ActionKeyContainer(defaultModifierKey)
+ PlusIconContainer()
+ }
+}
+
+@Composable
+private fun ActionKeyContainer(defaultModifierKey: ShortcutKey.Icon.ResIdIcon) {
+ Row(
+ modifier =
+ Modifier.height(48.dp)
+ .width(105.dp)
+ .background(
+ color = MaterialTheme.colorScheme.surface,
+ shape = RoundedCornerShape(16.dp),
+ )
+ .padding(all = 12.dp),
+ horizontalArrangement = Arrangement.spacedBy(8.dp),
+ ) {
+ ActionKeyIcon(defaultModifierKey)
+ ActionKeyText()
+ }
+}
+
+@Composable
+fun ActionKeyText() {
+ Text(
+ text = "Action",
+ style = MaterialTheme.typography.titleMedium,
+ fontSize = 16.sp,
+ lineHeight = 24.sp,
+ modifier = Modifier.wrapContentSize(Alignment.Center),
+ color = MaterialTheme.colorScheme.onSurface,
+ )
+}
+
+@Composable
+private fun ActionKeyIcon(defaultModifierKey: ShortcutKey.Icon.ResIdIcon) {
+ Icon(
+ painter = painterResource(id = defaultModifierKey.drawableResId),
+ contentDescription = stringResource(R.string.shortcut_helper_content_description_meta_key),
+ modifier = Modifier.size(24.dp).wrapContentSize(Alignment.Center),
+ )
+}
+
+@Composable
+private fun PlusIconContainer() {
+ Icon(
+ tint = MaterialTheme.colorScheme.onSurface,
+ imageVector = Icons.Default.Add,
+ contentDescription =
+ stringResource(id = R.string.shortcut_helper_content_description_plus_icon),
+ modifier = Modifier.padding(vertical = 12.dp).size(24.dp).wrapContentSize(Alignment.Center),
+ )
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelper.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelper.kt
index abddc70..13934ea 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelper.kt
@@ -110,6 +110,7 @@
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategoryType
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCommand
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutIcon
+import com.android.systemui.keyboard.shortcut.shared.model.ShortcutInfo
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutKey
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutSubCategory
import com.android.systemui.keyboard.shortcut.ui.model.IconSource
@@ -124,6 +125,7 @@
modifier: Modifier = Modifier,
shortcutsUiState: ShortcutsUiState,
useSinglePane: @Composable () -> Boolean = { shouldUseSinglePane() },
+ onCustomizationRequested: (ShortcutInfo) -> Unit = {},
) {
when (shortcutsUiState) {
is ShortcutsUiState.Active -> {
@@ -133,6 +135,7 @@
onSearchQueryChanged,
modifier,
onKeyboardSettingsClicked,
+ onCustomizationRequested,
)
}
else -> {
@@ -148,6 +151,7 @@
onSearchQueryChanged: (String) -> Unit,
modifier: Modifier,
onKeyboardSettingsClicked: () -> Unit,
+ onCustomizationRequested: (ShortcutInfo) -> Unit = {},
) {
var selectedCategoryType by
remember(shortcutsUiState.defaultSelectedCategory) {
@@ -173,6 +177,7 @@
onCategorySelected = { selectedCategoryType = it },
onKeyboardSettingsClicked,
shortcutsUiState.isShortcutCustomizerFlagEnabled,
+ onCustomizationRequested,
)
}
}
@@ -362,6 +367,7 @@
onCategorySelected: (ShortcutCategoryType?) -> Unit,
onKeyboardSettingsClicked: () -> Unit,
isShortcutCustomizerFlagEnabled: Boolean,
+ onCustomizationRequested: (ShortcutInfo) -> Unit = {},
) {
val selectedCategory = categories.fastFirstOrNull { it.type == selectedCategoryType }
var isCustomizeModeEntered by remember { mutableStateOf(false) }
@@ -400,6 +406,7 @@
Modifier.fillMaxSize().padding(top = 8.dp),
selectedCategory,
isCustomizing = isCustomizing,
+ onCustomizationRequested = onCustomizationRequested,
)
}
}
@@ -434,6 +441,7 @@
modifier: Modifier,
category: ShortcutCategoryUi?,
isCustomizing: Boolean,
+ onCustomizationRequested: (ShortcutInfo) -> Unit = {},
) {
val listState = rememberLazyListState()
LaunchedEffect(key1 = category) { if (category != null) listState.animateScrollToItem(0) }
@@ -447,6 +455,15 @@
searchQuery = searchQuery,
subCategory = subcategory,
isCustomizing = isCustomizing,
+ onCustomizationRequested = { label, subCategoryLabel ->
+ onCustomizationRequested(
+ ShortcutInfo(
+ label = label,
+ subCategoryLabel = subCategoryLabel,
+ categoryType = category.type,
+ )
+ )
+ },
)
Spacer(modifier = Modifier.height(8.dp))
}
@@ -476,6 +493,7 @@
searchQuery: String,
subCategory: ShortcutSubCategory,
isCustomizing: Boolean,
+ onCustomizationRequested: (String, String) -> Unit = { _: String, _: String -> },
) {
Surface(
modifier = Modifier.fillMaxWidth(),
@@ -497,6 +515,7 @@
searchQuery = searchQuery,
shortcut = shortcut,
isCustomizing = isCustomizing,
+ onCustomizationRequested = { onCustomizationRequested(it, subCategory.label) },
)
}
}
@@ -518,6 +537,7 @@
searchQuery: String,
shortcut: ShortcutModel,
isCustomizing: Boolean = false,
+ onCustomizationRequested: (String) -> Unit = {},
) {
val interactionSource = remember { MutableInteractionSource() }
val isFocused by interactionSource.collectIsFocusedAsState()
@@ -541,7 +561,12 @@
ShortcutDescriptionText(searchQuery = searchQuery, shortcut = shortcut)
}
Spacer(modifier = Modifier.width(24.dp))
- ShortcutKeyCombinations(modifier = Modifier.weight(1f), shortcut = shortcut, isCustomizing)
+ ShortcutKeyCombinations(
+ modifier = Modifier.weight(1f),
+ shortcut = shortcut,
+ isCustomizing = isCustomizing,
+ onAddShortcutClicked = { onCustomizationRequested(shortcut.label) },
+ )
}
}
@@ -569,6 +594,7 @@
modifier: Modifier = Modifier,
shortcut: ShortcutModel,
isCustomizing: Boolean = false,
+ onAddShortcutClicked: () -> Unit = {},
) {
FlowRow(
modifier = modifier,
@@ -590,7 +616,7 @@
color = MaterialTheme.colorScheme.outline,
shape = CircleShape,
),
- onClick = {},
+ onClick = { onAddShortcutClicked() },
color = Color.Transparent,
width = 32.dp,
height = 32.dp,
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/Surfaces.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/Surfaces.kt
index 435968e..e761c73 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/Surfaces.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/Surfaces.kt
@@ -44,6 +44,7 @@
import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.LocalTonalElevationEnabled
import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.contentColorFor
import androidx.compose.material3.minimumInteractiveComponentSize
@@ -283,6 +284,108 @@
}
@Composable
+fun ShortcutHelperButton(
+ modifier: Modifier = Modifier,
+ onClick: () -> Unit,
+ shape: Shape = RoundedCornerShape(360.dp),
+ color: Color,
+ width: Dp,
+ height: Dp = 40.dp,
+ iconSource: IconSource = IconSource(),
+ text: String? = null,
+ contentColor: Color,
+ contentPaddingHorizontal: Dp = 16.dp,
+ contentPaddingVertical: Dp = 10.dp,
+ enabled: Boolean = true,
+) {
+ ShortcutHelperButtonSurface(
+ onClick = onClick,
+ shape = shape,
+ color = color,
+ modifier = modifier,
+ enabled = enabled,
+ width = width,
+ height = height,
+ ) {
+ Row(
+ modifier =
+ Modifier.padding(
+ horizontal = contentPaddingHorizontal,
+ vertical = contentPaddingVertical,
+ ),
+ verticalAlignment = Alignment.CenterVertically,
+ horizontalArrangement = Arrangement.Center,
+ ) {
+ if (iconSource.imageVector != null) {
+ Icon(
+ tint = contentColor,
+ imageVector = iconSource.imageVector,
+ contentDescription =
+ null, // TODO this probably should not be null for accessibility.
+ modifier = Modifier.size(20.dp).wrapContentSize(Alignment.Center),
+ )
+ }
+
+ if (iconSource.imageVector != null && text != null)
+ Spacer(modifier = Modifier.weight(1f))
+
+ if (text != null) {
+ Text(
+ text,
+ color = contentColor,
+ fontSize = 14.sp,
+ style = MaterialTheme.typography.labelLarge,
+ modifier = Modifier.wrapContentSize(Alignment.Center),
+ )
+ }
+ }
+ }
+}
+
+@Composable
+fun ShortcutHelperButtonSurface(
+ onClick: () -> Unit,
+ shape: Shape,
+ color: Color,
+ modifier: Modifier = Modifier,
+ enabled: Boolean,
+ width: Dp,
+ height: Dp,
+ content: @Composable () -> Unit,
+) {
+ if (enabled) {
+ ClickableShortcutSurface(
+ onClick = onClick,
+ shape = shape,
+ color = color,
+ modifier = modifier.semantics { role = Role.Button }.width(width).height(height),
+ interactionsConfig =
+ InteractionsConfig(
+ hoverOverlayColor = MaterialTheme.colorScheme.onSurface,
+ hoverOverlayAlpha = 0.11f,
+ pressedOverlayColor = MaterialTheme.colorScheme.onSurface,
+ pressedOverlayAlpha = 0.15f,
+ focusOutlineColor = MaterialTheme.colorScheme.secondary,
+ focusOutlineStrokeWidth = 3.dp,
+ focusOutlinePadding = 2.dp,
+ surfaceCornerRadius = 28.dp,
+ focusOutlineCornerRadius = 33.dp,
+ ),
+ ) {
+ content()
+ }
+ } else {
+ Surface(
+ shape = shape,
+ color = color.copy(0.38f),
+ modifier = modifier.semantics { role = Role.Button }.width(width).height(height),
+ ) {
+ content()
+ }
+ }
+}
+
+@Composable
private fun surfaceColorAtElevation(color: Color, elevation: Dp): Color {
return MaterialTheme.colorScheme.applyTonalElevation(color, elevation)
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/model/ShortcutCustomizationUiState.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/model/ShortcutCustomizationUiState.kt
new file mode 100644
index 0000000..e9f2a3b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/model/ShortcutCustomizationUiState.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyboard.shortcut.ui.model
+
+import com.android.systemui.keyboard.shortcut.shared.model.ShortcutKey
+
+sealed interface ShortcutCustomizationUiState {
+ data class AddShortcutDialog(
+ val shortcutLabel: String,
+ val shouldShowErrorMessage: Boolean,
+ val isValidKeyCombination: Boolean,
+ val defaultCustomShortcutModifierKey: ShortcutKey.Icon.ResIdIcon,
+ val isDialogShowing: Boolean,
+ ) : ShortcutCustomizationUiState
+
+ data object Inactive : ShortcutCustomizationUiState
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutCustomizationViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutCustomizationViewModel.kt
new file mode 100644
index 0000000..b925387
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutCustomizationViewModel.kt
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyboard.shortcut.ui.viewmodel
+
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.ui.input.key.KeyEvent
+import com.android.systemui.keyboard.shortcut.domain.interactor.ShortcutCustomizationInteractor
+import com.android.systemui.keyboard.shortcut.shared.model.ShortcutInfo
+import com.android.systemui.keyboard.shortcut.ui.model.ShortcutCustomizationUiState
+import dagger.assisted.AssistedFactory
+import dagger.assisted.AssistedInject
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.flow.update
+
+class ShortcutCustomizationViewModel
+@AssistedInject
+constructor(private val shortcutCustomizationInteractor: ShortcutCustomizationInteractor) {
+ private val _shortcutBeingCustomized = mutableStateOf<ShortcutInfo?>(null)
+
+ private val _shortcutCustomizationUiState =
+ MutableStateFlow<ShortcutCustomizationUiState>(ShortcutCustomizationUiState.Inactive)
+
+ val shortcutCustomizationUiState = _shortcutCustomizationUiState.asStateFlow()
+
+ fun onAddShortcutDialogRequested(shortcutBeingCustomized: ShortcutInfo) {
+ _shortcutCustomizationUiState.value =
+ ShortcutCustomizationUiState.AddShortcutDialog(
+ shortcutLabel = shortcutBeingCustomized.label,
+ shouldShowErrorMessage = false,
+ isValidKeyCombination = false,
+ defaultCustomShortcutModifierKey =
+ shortcutCustomizationInteractor.getDefaultCustomShortcutModifierKey(),
+ isDialogShowing = false,
+ )
+
+ _shortcutBeingCustomized.value = shortcutBeingCustomized
+ }
+
+ fun onAddShortcutDialogShown() {
+ _shortcutCustomizationUiState.update { uiState ->
+ (uiState as? ShortcutCustomizationUiState.AddShortcutDialog)
+ ?.let { it.copy(isDialogShowing = true) }
+ ?: uiState
+ }
+ }
+
+ fun onAddShortcutDialogDismissed() {
+ _shortcutBeingCustomized.value = null
+ _shortcutCustomizationUiState.value = ShortcutCustomizationUiState.Inactive
+ }
+
+ fun onKeyPressed(keyEvent: KeyEvent): Boolean {
+ // TODO Not yet implemented b/373638584
+ return false
+ }
+
+ @AssistedFactory
+ interface Factory {
+ fun create(): ShortcutCustomizationViewModel
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
index 53177de..f49693a 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -1191,11 +1191,13 @@
}
private void pilferPointers() {
- // Capture inputs
- mInputMonitor.pilferPointers();
- // Notify FalsingManager that an intentional gesture has occurred.
- mFalsingManager.isFalseTouch(BACK_GESTURE);
- mInputEventReceiver.setBatchingEnabled(true);
+ if (mInputMonitor != null) {
+ // Capture inputs
+ mInputMonitor.pilferPointers();
+ // Notify FalsingManager that an intentional gesture has occurred.
+ mFalsingManager.isFalseTouch(BACK_GESTURE);
+ mInputEventReceiver.setBatchingEnabled(true);
+ }
}
private boolean isButtonPressFromTrackpad(MotionEvent ev) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt b/packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt
index a1071907..2a5ffc6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt
@@ -27,6 +27,7 @@
import android.content.IntentFilter
import android.content.pm.PackageManager
import android.content.pm.UserInfo
+import android.content.res.Resources
import android.graphics.drawable.Drawable
import android.os.IBinder
import android.os.PowerExemptionManager
@@ -54,6 +55,7 @@
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags.TASK_MANAGER_SHOW_USER_VISIBLE_JOBS
import com.android.internal.jank.InteractionJankMonitor
import com.android.systemui.Dumpable
+import com.android.systemui.Flags;
import com.android.systemui.res.R
import com.android.systemui.animation.DialogCuj
import com.android.systemui.animation.DialogTransitionAnimator
@@ -137,7 +139,7 @@
@SysUISingleton
class FgsManagerControllerImpl @Inject constructor(
- private val context: Context,
+ @Main private val resources: Resources,
@Main private val mainExecutor: Executor,
@Background private val backgroundExecutor: Executor,
private val systemClock: SystemClock,
@@ -223,6 +225,14 @@
private val userVisibleJobObserver = UserVisibleJobObserver()
+ private val stoppableApps by lazy { resources
+ .getStringArray(com.android.internal.R.array.stoppable_fgs_system_apps)
+ }
+
+ private val vendorStoppableApps by lazy { resources
+ .getStringArray(com.android.internal.R.array.vendor_stoppable_fgs_system_apps)
+ }
+
override fun init() {
synchronized(lock) {
if (initialized) {
@@ -725,9 +735,22 @@
}
else -> UIControl.NORMAL
}
+ // If the app wants to be a good citizen by being stoppable, even if the category it
+ // belongs to is exempted for background restriction, let it be stoppable by user.
+ if (Flags.stoppableFgsSystemApp()) {
+ if (isStoppableApp(packageName)) {
+ uiControl = UIControl.NORMAL
+ }
+ }
+
uiControlInitialized = true
}
+ fun isStoppableApp(packageName: String): Boolean {
+ return stoppableApps.contains(packageName) ||
+ vendorStoppableApps.contains(packageName)
+ }
+
override fun equals(other: Any?): Boolean {
if (other !is UserPackage) {
return false
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index ce9c441..a5eb92b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -24,7 +24,10 @@
import static android.view.MotionEvent.ACTION_DOWN;
import static android.view.MotionEvent.ACTION_UP;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON;
+import static android.window.BackEvent.EDGE_NONE;
+import static com.android.window.flags.Flags.predictiveBackSwipeEdgeNoneApi;
+import static com.android.window.flags.Flags.predictiveBackThreeButtonNav;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SYSUI_PROXY;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_UNFOLD_ANIMATION_FORWARDER;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_UNLOCK_ANIMATION_CONTROLLER;
@@ -41,6 +44,7 @@
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_WAKEFULNESS_TRANSITION;
import android.annotation.FloatRange;
+import android.annotation.Nullable;
import android.app.ActivityTaskManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -114,6 +118,7 @@
import com.android.systemui.statusbar.phone.StatusBarWindowCallback;
import com.android.systemui.statusbar.policy.CallbackController;
import com.android.systemui.unfold.progress.UnfoldTransitionProgressForwarder;
+import com.android.wm.shell.back.BackAnimation;
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus;
import com.android.wm.shell.sysui.ShellInterface;
@@ -174,6 +179,7 @@
private Region mActiveNavBarRegion;
private final BroadcastDispatcher mBroadcastDispatcher;
+ private final BackAnimation mBackAnimation;
private IOverviewProxy mOverviewProxy;
private int mConnectionBackoffAttempts;
@@ -287,11 +293,18 @@
}
@Override
- public void onBackPressed() {
- verifyCallerAndClearCallingIdentityPostMain("onBackPressed", () -> {
- sendEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK);
- sendEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK);
- });
+ public void onBackEvent(@Nullable KeyEvent keyEvent) throws RemoteException {
+ if (predictiveBackThreeButtonNav() && predictiveBackSwipeEdgeNoneApi()
+ && mBackAnimation != null && keyEvent != null) {
+ mBackAnimation.setTriggerBack(!keyEvent.isCanceled());
+ mBackAnimation.onBackMotion(/* touchX */ 0, /* touchY */ 0, keyEvent.getAction(),
+ EDGE_NONE);
+ } else {
+ verifyCallerAndClearCallingIdentityPostMain("onBackPressed", () -> {
+ sendEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK);
+ sendEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK);
+ });
+ }
}
@Override
@@ -657,7 +670,8 @@
AssistUtils assistUtils,
DumpManager dumpManager,
Optional<UnfoldTransitionProgressForwarder> unfoldTransitionProgressForwarder,
- BroadcastDispatcher broadcastDispatcher
+ BroadcastDispatcher broadcastDispatcher,
+ Optional<BackAnimation> backAnimation
) {
// b/241601880: This component should only be running for primary users or
// secondaryUsers when visibleBackgroundUsers are supported.
@@ -695,6 +709,7 @@
mDisplayTracker = displayTracker;
mUnfoldTransitionProgressForwarder = unfoldTransitionProgressForwarder;
mBroadcastDispatcher = broadcastDispatcher;
+ mBackAnimation = backAnimation.orElse(null);
if (!KeyguardWmStateRefactor.isEnabled()) {
mSysuiUnlockAnimationController = sysuiUnlockAnimationController;
diff --git a/packages/SystemUI/src/com/android/systemui/settings/DisplayTrackerImpl.kt b/packages/SystemUI/src/com/android/systemui/settings/DisplayTrackerImpl.kt
index 2ef27a8..60ed2de 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/DisplayTrackerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/settings/DisplayTrackerImpl.kt
@@ -17,7 +17,7 @@
package com.android.systemui.settings
import android.hardware.display.DisplayManager
-import android.hardware.display.DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS
+import android.hardware.display.DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS
import android.os.Handler
import android.view.Display
import androidx.annotation.GuardedBy
@@ -32,7 +32,7 @@
class DisplayTrackerImpl
internal constructor(
val displayManager: DisplayManager,
- @Background val backgroundHandler: Handler
+ @Background val backgroundHandler: Handler,
) : DisplayTracker {
override val defaultDisplayId: Int = Display.DEFAULT_DISPLAY
override val allDisplays: Array<Display>
@@ -47,27 +47,21 @@
val displayChangedListener: DisplayManager.DisplayListener =
object : DisplayManager.DisplayListener {
override fun onDisplayAdded(displayId: Int) {
- traceSection(
- "DisplayTrackerImpl.displayChangedDisplayListener#onDisplayAdded",
- ) {
+ traceSection("DisplayTrackerImpl.displayChangedDisplayListener#onDisplayAdded") {
val list = synchronized(displayCallbacks) { displayCallbacks.toList() }
onDisplayAdded(displayId, list)
}
}
override fun onDisplayRemoved(displayId: Int) {
- traceSection(
- "DisplayTrackerImpl.displayChangedDisplayListener#onDisplayRemoved",
- ) {
+ traceSection("DisplayTrackerImpl.displayChangedDisplayListener#onDisplayRemoved") {
val list = synchronized(displayCallbacks) { displayCallbacks.toList() }
onDisplayRemoved(displayId, list)
}
}
override fun onDisplayChanged(displayId: Int) {
- traceSection(
- "DisplayTrackerImpl.displayChangedDisplayListener#onDisplayChanged",
- ) {
+ traceSection("DisplayTrackerImpl.displayChangedDisplayListener#onDisplayChanged") {
val list = synchronized(displayCallbacks) { displayCallbacks.toList() }
onDisplayChanged(displayId, list)
}
@@ -83,7 +77,7 @@
override fun onDisplayChanged(displayId: Int) {
traceSection(
- "DisplayTrackerImpl.displayBrightnessChangedDisplayListener#onDisplayChanged",
+ "DisplayTrackerImpl.displayBrightnessChangedDisplayListener#onDisplayChanged"
) {
val list = synchronized(brightnessCallbacks) { brightnessCallbacks.toList() }
onDisplayChanged(displayId, list)
@@ -102,14 +96,15 @@
override fun addBrightnessChangeCallback(
callback: DisplayTracker.Callback,
- executor: Executor
+ executor: Executor,
) {
synchronized(brightnessCallbacks) {
if (brightnessCallbacks.isEmpty()) {
displayManager.registerDisplayListener(
displayBrightnessChangedListener,
backgroundHandler,
- EVENT_FLAG_DISPLAY_BRIGHTNESS
+ /* eventFlags */ 0,
+ PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS,
)
}
brightnessCallbacks.add(DisplayTrackerDataItem(WeakReference(callback), executor))
@@ -159,7 +154,7 @@
private inline fun notifySubscribers(
crossinline action: DisplayTracker.Callback.() -> Unit,
- list: List<DisplayTrackerDataItem>
+ list: List<DisplayTrackerDataItem>,
) {
list.forEach {
if (it.callback.get() != null) {
@@ -170,7 +165,7 @@
private data class DisplayTrackerDataItem(
val callback: WeakReference<DisplayTracker.Callback>,
- val executor: Executor
+ val executor: Executor,
) {
fun sameOrEmpty(other: DisplayTracker.Callback): Boolean {
return callback.get()?.equals(other) ?: true
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index 3d9eb53..a39ca5d 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -103,6 +103,7 @@
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
+import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.FlagsParameterization;
import android.service.dreams.IDreamManager;
import android.service.trust.TrustAgentService;
@@ -129,6 +130,7 @@
import com.android.keyguard.logging.KeyguardUpdateMonitorLogger;
import com.android.keyguard.logging.SimLogger;
import com.android.settingslib.fuelgauge.BatteryStatus;
+import com.android.systemui.Flags;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.biometrics.AuthController;
import com.android.systemui.biometrics.FingerprintInteractiveToAuthProvider;
@@ -190,6 +192,7 @@
@SmallTest
@RunWith(ParameterizedAndroidJunit4.class)
@TestableLooper.RunWithLooper
+@EnableFlags(Flags.FLAG_USER_ENCRYPTED_SOURCE)
public class KeyguardUpdateMonitorTest extends SysuiTestCase {
private static final String PKG_ALLOWING_FP_LISTEN_ON_OCCLUDING_ACTIVITY =
"test_app_fp_listen_on_occluding_activity";
@@ -1292,12 +1295,15 @@
@Test
public void testIsUserUnlocked() {
+ when(mUserManager.isUserUnlocked(mSelectedUserInteractor.getSelectedUserId())).thenReturn(
+ true);
// mUserManager will report the user as unlocked on @Before
assertThat(
mKeyguardUpdateMonitor.isUserUnlocked(mSelectedUserInteractor.getSelectedUserId()))
.isTrue();
// Invalid user should not be unlocked.
int randomUser = 99;
+ when(mUserManager.isUserUnlocked(randomUser)).thenReturn(false);
assertThat(mKeyguardUpdateMonitor.isUserUnlocked(randomUser)).isFalse();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.kt b/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.kt
index 3bfde68..9096808 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.kt
@@ -59,6 +59,7 @@
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.time.FakeSystemClock
+import com.android.wm.shell.back.BackAnimation
import com.android.wm.shell.sysui.ShellInterface
import com.google.common.util.concurrent.MoreExecutors
import java.util.Optional
@@ -120,6 +121,7 @@
private lateinit var unfoldTransitionProgressForwarder:
Optional<UnfoldTransitionProgressForwarder>
@Mock private lateinit var broadcastDispatcher: BroadcastDispatcher
+ @Mock private lateinit var backAnimation: Optional<BackAnimation>
@Before
fun setUp() {
@@ -289,6 +291,7 @@
dumpManager,
unfoldTransitionProgressForwarder,
broadcastDispatcher,
+ backAnimation,
)
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/settings/DisplayTrackerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/settings/DisplayTrackerImplTest.kt
index ae976a0..9fb752a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/settings/DisplayTrackerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/settings/DisplayTrackerImplTest.kt
@@ -17,7 +17,7 @@
package com.android.systemui.settings
import android.hardware.display.DisplayManager
-import android.hardware.display.DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS
+import android.hardware.display.DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS
import android.hardware.display.DisplayManagerGlobal
import android.os.Handler
import android.testing.AndroidTestingRunner
@@ -59,14 +59,14 @@
DisplayManagerGlobal.getInstance(),
Display.DEFAULT_DISPLAY,
DisplayInfo(),
- DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS
+ DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS,
)
mSecondaryDisplay =
Display(
DisplayManagerGlobal.getInstance(),
Display.DEFAULT_DISPLAY + 1,
DisplayInfo(),
- DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS
+ DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS,
)
`when`(displayManager.displays).thenReturn(arrayOf(mDefaultDisplay, mSecondaryDisplay))
@@ -94,7 +94,12 @@
fun registerBrightnessCallback_registersDisplayListener() {
tracker.addBrightnessChangeCallback(TestCallback(), executor)
verify(displayManager)
- .registerDisplayListener(any(), any(), eq(EVENT_FLAG_DISPLAY_BRIGHTNESS))
+ .registerDisplayListener(
+ any(),
+ any(),
+ eq(0L),
+ eq(PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS),
+ )
}
@Test
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/shortcut/KeyboardShortcutHelperKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/shortcut/KeyboardShortcutHelperKosmos.kt
index c41493e..8022e6e 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/shortcut/KeyboardShortcutHelperKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/shortcut/KeyboardShortcutHelperKosmos.kt
@@ -31,8 +31,11 @@
import com.android.systemui.keyboard.shortcut.data.source.KeyboardShortcutGroupsSource
import com.android.systemui.keyboard.shortcut.data.source.MultitaskingShortcutsSource
import com.android.systemui.keyboard.shortcut.data.source.SystemShortcutsSource
+import com.android.systemui.keyboard.shortcut.domain.interactor.ShortcutCustomizationInteractor
import com.android.systemui.keyboard.shortcut.domain.interactor.ShortcutHelperCategoriesInteractor
import com.android.systemui.keyboard.shortcut.domain.interactor.ShortcutHelperStateInteractor
+import com.android.systemui.keyboard.shortcut.ui.ShortcutCustomizationDialogStarter
+import com.android.systemui.keyboard.shortcut.ui.viewmodel.ShortcutCustomizationViewModel
import com.android.systemui.keyboard.shortcut.ui.viewmodel.ShortcutHelperViewModel
import com.android.systemui.keyguard.data.repository.fakeCommandQueue
import com.android.systemui.kosmos.Kosmos
@@ -42,6 +45,7 @@
import com.android.systemui.model.sysUiState
import com.android.systemui.settings.displayTracker
import com.android.systemui.settings.userTracker
+import com.android.systemui.statusbar.phone.systemUIDialogFactory
var Kosmos.shortcutHelperAppCategoriesShortcutsSource: KeyboardShortcutGroupsSource by
Kosmos.Fixture { AppCategoriesShortcutsSource(windowManager, testDispatcher) }
@@ -121,3 +125,26 @@
shortcutHelperCategoriesInteractor,
)
}
+
+val Kosmos.shortcutCustomizationDialogStarterFactory by
+ Kosmos.Fixture {
+ object : ShortcutCustomizationDialogStarter.Factory {
+ override fun create(): ShortcutCustomizationDialogStarter {
+ return ShortcutCustomizationDialogStarter(
+ shortcutCustomizationViewModelFactory,
+ systemUIDialogFactory,
+ )
+ }
+ }
+ }
+
+val Kosmos.shortcutCustomizationInteractor by Kosmos.Fixture { ShortcutCustomizationInteractor() }
+
+val Kosmos.shortcutCustomizationViewModelFactory by
+ Kosmos.Fixture {
+ object : ShortcutCustomizationViewModel.Factory {
+ override fun create(): ShortcutCustomizationViewModel {
+ return ShortcutCustomizationViewModel(shortcutCustomizationInteractor)
+ }
+ }
+ }
diff --git a/ravenwood/Android.bp b/ravenwood/Android.bp
index 4731cfb..0c2ce8d 100644
--- a/ravenwood/Android.bp
+++ b/ravenwood/Android.bp
@@ -376,6 +376,7 @@
":ravenwood-empty-res",
":framework-platform-compat-config",
":services-platform-compat-config",
+ "texts/ravenwood-build.prop",
],
device_first_srcs: [
":apex_icu.dat",
diff --git a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java
index e61a054..678a97b 100644
--- a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java
+++ b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java
@@ -22,7 +22,6 @@
import static com.android.ravenwood.common.RavenwoodCommonUtils.RAVENWOOD_RESOURCE_APK;
import static com.android.ravenwood.common.RavenwoodCommonUtils.RAVENWOOD_VERBOSE_LOGGING;
import static com.android.ravenwood.common.RavenwoodCommonUtils.RAVENWOOD_VERSION_JAVA_SYSPROP;
-import static com.android.ravenwood.common.RavenwoodCommonUtils.getRavenwoodRuntimePath;
import static org.junit.Assert.assertThrows;
import static org.mockito.ArgumentMatchers.any;
@@ -95,8 +94,6 @@
private static final String LIBRAVENWOOD_INITIALIZER_NAME = "ravenwood_initializer";
private static final String RAVENWOOD_NATIVE_SYSPROP_NAME = "ravenwood_sysprop";
private static final String RAVENWOOD_NATIVE_RUNTIME_NAME = "ravenwood_runtime";
- private static final String RAVENWOOD_BUILD_PROP =
- getRavenwoodRuntimePath() + "ravenwood-data/build.prop";
/**
* When enabled, attempt to dump all thread stacks just before we hit the
@@ -209,7 +206,7 @@
System.load(RavenwoodCommonUtils.getJniLibraryPath(RAVENWOOD_NATIVE_RUNTIME_NAME));
// Do the basic set up for the android sysprops.
- RavenwoodSystemProperties.initialize(RAVENWOOD_BUILD_PROP);
+ RavenwoodSystemProperties.initialize();
setSystemProperties(null);
// Do this after loading RAVENWOOD_NATIVE_RUNTIME_NAME (which backs Os.setenv()),
diff --git a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodSystemProperties.java b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodSystemProperties.java
index 9bc45be..3e4619f 100644
--- a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodSystemProperties.java
+++ b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodSystemProperties.java
@@ -16,21 +16,30 @@
package android.platform.test.ravenwood;
-import static com.android.ravenwood.common.RavenwoodCommonUtils.RAVENWOOD_SYSPROP;
+import static com.android.ravenwood.common.RavenwoodCommonUtils.RAVENWOOD_VERBOSE_LOGGING;
+import static com.android.ravenwood.common.RavenwoodCommonUtils.getRavenwoodRuntimePath;
-import com.android.ravenwood.common.RavenwoodCommonUtils;
+import android.util.Log;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
public class RavenwoodSystemProperties {
private static final String TAG = "RavenwoodSystemProperties";
+ /** We pull in propeties from this file. */
+ private static final String RAVENWOOD_BUILD_PROP = "ravenwood-data/ravenwood-build.prop";
+
+ /** This is the actual build.prop we use to build the device (contents depends on lunch). */
+ private static final String DEVICE_BUILD_PROP = "ravenwood-data/build.prop";
+
+ /** The default values. */
private static final Map<String, String> sDefaultValues = new HashMap<>();
private static final String[] PARTITIONS = {
@@ -43,52 +52,54 @@
"vendor_dlkm",
};
- /**
- * More info about property file loading: system/core/init/property_service.cpp
- * In the following logic, the only partition we would need to consider is "system",
- * since we only read from system-build.prop
- */
- static void initialize(String propFile) {
- // Load all properties from build.prop
+ private static Map<String, String> readProperties(String propFile) {
+ // Use an ordered map just for cleaner dump log.
+ final Map<String, String> ret = new LinkedHashMap<>();
try {
Files.readAllLines(Path.of(propFile)).stream()
.map(String::trim)
.filter(s -> !s.startsWith("#"))
.map(s -> s.split("\\s*=\\s*", 2))
.filter(a -> a.length == 2)
- .forEach(a -> sDefaultValues.put(a[0], a[1]));
+ .forEach(a -> ret.put(a[0], a[1]));
} catch (IOException e) {
throw new RuntimeException(e);
}
+ return ret;
+ }
- // If ro.product.${name} is not set, derive from ro.product.${partition}.${name}
- // If ro.product.cpu.abilist* is not set, derive from ro.${partition}.product.cpu.abilist*
- for (var entry : Set.copyOf(sDefaultValues.entrySet())) {
- final String key;
- if (entry.getKey().startsWith("ro.product.system.")) {
- var name = entry.getKey().substring(18);
- key = "ro.product." + name;
+ /**
+ * Load default sysprops from {@link #RAVENWOOD_BUILD_PROP}. We also pull in
+ * certain properties from the acutual device's build.prop {@link #DEVICE_BUILD_PROP} too.
+ *
+ * More info about property file loading: system/core/init/property_service.cpp
+ * In the following logic, the only partition we would need to consider is "system",
+ * since we only read from system-build.prop
+ */
+ static void initialize() {
+ var path = getRavenwoodRuntimePath();
+ var ravenwoodProps = readProperties(path + RAVENWOOD_BUILD_PROP);
+ var deviceProps = readProperties(path + DEVICE_BUILD_PROP);
- } else if (entry.getKey().startsWith("ro.system.product.cpu.abilist")) {
- var name = entry.getKey().substring(22);
- key = "ro.product.cpu." + name;
+ Log.i(TAG, "Default system properties:");
+ ravenwoodProps.forEach((key, origValue) -> {
+ final String value;
+
+ // If a value starts with "$$$", then this is a reference to the device-side value.
+ if (origValue.startsWith("$$$")) {
+ var deviceKey = origValue.substring(3);
+ var deviceValue = deviceProps.get(deviceKey);
+ if (deviceValue == null) {
+ throw new RuntimeException("Failed to initialize system properties. Key '"
+ + deviceKey + "' doesn't exist in the device side build.prop");
+ }
+ value = deviceValue;
} else {
- continue;
+ value = origValue;
}
- if (!sDefaultValues.containsKey(key)) {
- sDefaultValues.put(key, entry.getValue());
- }
- }
-
- // Some other custom values
- sDefaultValues.put("ro.board.first_api_level", "1");
- sDefaultValues.put("ro.product.first_api_level", "1");
- sDefaultValues.put("ro.soc.manufacturer", "Android");
- sDefaultValues.put("ro.soc.model", "Ravenwood");
- sDefaultValues.put(RAVENWOOD_SYSPROP, "1");
-
- // Log all values
- sDefaultValues.forEach((key, value) -> RavenwoodCommonUtils.log(TAG, key + "=" + value));
+ Log.i(TAG, key + "=" + value);
+ sDefaultValues.put(key, value);
+ });
// Copy ro.product.* and ro.build.* to all partitions, just in case
// We don't want to log these because these are just a lot of duplicate values
@@ -104,6 +115,13 @@
}
}
}
+ if (RAVENWOOD_VERBOSE_LOGGING) {
+ // Dump all properties for local debugging.
+ Log.v(TAG, "All system properties:");
+ for (var key : sDefaultValues.keySet().stream().sorted().toList()) {
+ Log.v(TAG, "" + key + "=" + sDefaultValues.get(key));
+ }
+ }
}
private volatile boolean mIsImmutable;
diff --git a/ravenwood/scripts/run-ravenwood-tests.sh b/ravenwood/scripts/run-ravenwood-tests.sh
index 1910100..fe2269a 100755
--- a/ravenwood/scripts/run-ravenwood-tests.sh
+++ b/ravenwood/scripts/run-ravenwood-tests.sh
@@ -33,7 +33,7 @@
exclude_re=""
smoke_exclude_re=""
dry_run=""
-while getopts "sx:f:d" opt; do
+while getopts "sx:f:dt" opt; do
case "$opt" in
s)
# Remove slow tests.
@@ -51,6 +51,9 @@
# Dry run
dry_run="echo"
;;
+ t)
+ export RAVENWOOD_LOG_OUT=$(tty)
+ ;;
'?')
exit 1
;;
diff --git a/ravenwood/texts/build.prop-sample-cuttlefish b/ravenwood/texts/build.prop-sample-cuttlefish
new file mode 100644
index 0000000..f78b727
--- /dev/null
+++ b/ravenwood/texts/build.prop-sample-cuttlefish
@@ -0,0 +1,132 @@
+# This is file is generated with `aosp_cf_x86_64_phone-trunk_staging-eng` on 2024-11-06.
+# We have this file here only as a reference. We don't actually use this file anywhere.
+
+####################################
+# from generate_common_build_props
+# These properties identify this partition image.
+####################################
+ro.product.system.brand=Android
+ro.product.system.device=generic
+ro.product.system.manufacturer=Android
+ro.product.system.model=mainline
+ro.product.system.name=mainline
+ro.system.product.cpu.abilist=x86_64,x86,arm64-v8a,armeabi-v7a,armeabi
+ro.system.product.cpu.abilist32=x86,armeabi-v7a,armeabi
+ro.system.product.cpu.abilist64=x86_64,arm64-v8a
+ro.system.build.date=Tue Nov 5 13:25:43 PST 2024
+ro.system.build.date.utc=1730841943
+ro.system.build.fingerprint=generic/aosp_cf_x86_64_phone/vsoc_x86_64:Baklava/MAIN/eng.omakot:eng/test-keys
+ro.system.build.id=MAIN
+ro.system.build.tags=test-keys
+ro.system.build.type=eng
+ro.system.build.version.incremental=eng.omakot
+ro.system.build.version.release=15
+ro.system.build.version.release_or_codename=Baklava
+ro.system.build.version.sdk=35
+####################################
+# from gen_build_prop.py:generate_build_info
+####################################
+# begin build properties
+ro.build.legacy.id=MAIN
+ro.build.display.id=aosp_cf_x86_64_phone-eng Baklava MAIN eng.omakot test-keys
+ro.build.version.incremental=eng.omakot
+ro.build.version.sdk=35
+ro.build.version.preview_sdk=1
+ro.build.version.preview_sdk_fingerprint=2ef06129940d459014cf4dede3950d71
+ro.build.version.codename=Baklava
+ro.build.version.all_codenames=Baklava
+ro.build.version.known_codenames=Base,Base11,Cupcake,Donut,Eclair,Eclair01,EclairMr1,Froyo,Gingerbread,GingerbreadMr1,Honeycomb,HoneycombMr1,HoneycombMr2,IceCreamSandwich,IceCreamSandwichMr1,JellyBean,JellyBeanMr1,JellyBeanMr2,Kitkat,KitkatWatch,Lollipop,LollipopMr1,M,N,NMr1,O,OMr1,P,Q,R,S,Sv2,Tiramisu,UpsideDownCake,VanillaIceCream,Baklava
+ro.build.version.release=15
+ro.build.version.release_or_codename=Baklava
+ro.build.version.release_or_preview_display=Baklava
+ro.build.version.security_patch=2024-08-05
+ro.build.version.base_os=
+ro.build.version.min_supported_target_sdk=28
+ro.build.date=Tue Nov 5 13:25:43 PST 2024
+ro.build.date.utc=1730841943
+ro.build.type=eng
+ro.build.user=omakoto
+ro.build.host=omakoto-ct1.c.googlers.com
+ro.build.tags=test-keys
+ro.build.flavor=aosp_cf_x86_64_phone-eng
+# ro.product.cpu.abi and ro.product.cpu.abi2 are obsolete,
+# use ro.product.cpu.abilist instead.
+ro.product.cpu.abi=x86_64
+ro.product.locale=en-US
+ro.wifi.channels=
+# ro.build.product is obsolete; use ro.product.device
+ro.build.product=vsoc_x86_64
+# Do not try to parse description or thumbprint
+ro.build.description=aosp_cf_x86_64_phone-eng Baklava MAIN eng.omakot test-keys
+# end build properties
+####################################
+# from variable ADDITIONAL_SYSTEM_PROPERTIES
+####################################
+ro.treble.enabled=true
+ro.llndk.api_level=202504
+ro.actionable_compatible_property.enabled=true
+persist.debug.dalvik.vm.core_platform_api_policy=just-warn
+ro.postinstall.fstab.prefix=/system
+ro.kernel.android.checkjni=1
+ro.secure=0
+ro.allow.mock.location=1
+dalvik.vm.lockprof.threshold=500
+ro.debuggable=1
+dalvik.vm.image-dex2oat-filter=extract
+init.svc_debug.no_fatal.zygote=true
+net.bt.name=Android
+ro.force.debuggable=0
+####################################
+# from variable PRODUCT_SYSTEM_PROPERTIES
+####################################
+debug.atrace.tags.enableflags=0
+persist.traced.enable=1
+dalvik.vm.image-dex2oat-Xms=64m
+dalvik.vm.image-dex2oat-Xmx=64m
+dalvik.vm.dex2oat-Xms=64m
+dalvik.vm.dex2oat-Xmx=512m
+dalvik.vm.usejit=true
+dalvik.vm.dexopt.secondary=true
+dalvik.vm.dexopt.thermal-cutoff=2
+dalvik.vm.appimageformat=lz4
+ro.dalvik.vm.native.bridge=0
+pm.dexopt.post-boot=verify
+pm.dexopt.first-boot=verify
+pm.dexopt.boot-after-ota=verify
+pm.dexopt.boot-after-mainline-update=verify
+pm.dexopt.install=speed-profile
+pm.dexopt.install-fast=skip
+pm.dexopt.install-bulk=speed-profile
+pm.dexopt.install-bulk-secondary=verify
+pm.dexopt.install-bulk-downgraded=verify
+pm.dexopt.install-bulk-secondary-downgraded=verify
+pm.dexopt.bg-dexopt=speed-profile
+pm.dexopt.ab-ota=speed-profile
+pm.dexopt.inactive=verify
+pm.dexopt.cmdline=verify
+pm.dexopt.shared=speed
+dalvik.vm.disable-art-service-dexopt=true
+dalvik.vm.disable-odrefresh=true
+dalvik.vm.dex2oat-resolve-startup-strings=true
+dalvik.vm.dex2oat-max-image-block-size=524288
+dalvik.vm.minidebuginfo=true
+dalvik.vm.dex2oat-minidebuginfo=true
+dalvik.vm.madvise.vdexfile.size=104857600
+dalvik.vm.madvise.odexfile.size=104857600
+dalvik.vm.madvise.artfile.size=4294967295
+dalvik.vm.usap_pool_enabled=false
+dalvik.vm.usap_refill_threshold=1
+dalvik.vm.usap_pool_size_max=3
+dalvik.vm.usap_pool_size_min=1
+dalvik.vm.usap_pool_refill_delay_ms=3000
+dalvik.vm.useartservice=true
+dalvik.vm.enable_pr_dexopt=true
+ro.cp_system_other_odex=1
+ro.apex.updatable=true
+ro.launcher.depth.widget=0
+####################################
+# from variable PRODUCT_SYSTEM_DEFAULT_PROPERTIES
+####################################
+# Auto-added by post_process_props.py
+persist.sys.usb.config=adb
+# end of file
diff --git a/ravenwood/texts/ravenwood-build.prop b/ravenwood/texts/ravenwood-build.prop
new file mode 100644
index 0000000..93a18cf
--- /dev/null
+++ b/ravenwood/texts/ravenwood-build.prop
@@ -0,0 +1,44 @@
+# This file contains system properties used on ravenwood.
+
+ro.is_on_ravenwood=1
+
+ro.board.first_api_level=1
+ro.product.first_api_level=1
+ro.soc.manufacturer=Android
+ro.soc.model=Ravenwood
+ro.debuggable=1
+
+# The ones starting with "ro.product" or "ro.bild" will be copied to all "partitions" too.
+# See RavenwoodSystemProperties.
+ro.product.brand=Android
+ro.product.device=Ravenwood
+ro.product.manufacturer=Android
+ro.product.model=Ravenwood
+ro.product.name=Ravenwood
+ro.product.cpu.abilist=x86_64
+ro.product.cpu.abilist32=
+ro.product.cpu.abilist64=x86_64
+
+ro.build.date=Thu Jan 01 00:00:00 GMT 2024
+ro.build.date.utc=1704092400
+ro.build.id=MAIN
+ro.build.tags=dev-keys
+ro.build.type=userdebug
+ro.build.version.incremental=userdebug.ravenwood.20240101
+
+# These are what we used to use on Ravenwood, copied here as a reference.
+#ro.build.version.codename=REL
+#ro.build.version.all_codenames=REL
+#ro.build.version.known_codenames=REL
+#ro.build.version.release=14
+#ro.build.version.release_or_codename=VanillaIceCream
+#ro.build.version.sdk=34
+
+# We pull in the following values from the real build.prop file.
+ro.build.version.codename=$$$ro.build.version.codename
+ro.build.version.all_codenames=$$$ro.build.version.codename
+ro.build.version.known_codenames=$$$ro.build.version.codename
+ro.build.version.release=$$$ro.build.version.release
+ro.build.version.release_or_codename=$$$ro.build.version.release_or_codename
+ro.build.version.release_or_preview_display=$$$ro.build.version.release_or_preview_display
+ro.build.version.sdk=$$$ro.build.version.sdk
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index 78bc658..3dcca14 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -22,6 +22,9 @@
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import static com.android.server.health.Utils.copyV1Battery;
+import static java.lang.Math.abs;
+
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.app.ActivityManager;
@@ -48,6 +51,7 @@
import android.os.Handler;
import android.os.IBatteryPropertiesRegistrar;
import android.os.IBinder;
+import android.os.Looper;
import android.os.OsProtoEnums;
import android.os.PowerManager;
import android.os.RemoteException;
@@ -67,6 +71,7 @@
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IBatteryStats;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.os.SomeArgs;
@@ -84,6 +89,7 @@
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.NoSuchElementException;
+import java.util.Objects;
import java.util.concurrent.CopyOnWriteArraySet;
/**
@@ -149,19 +155,112 @@
private HealthInfo mHealthInfo;
private final HealthInfo mLastHealthInfo = new HealthInfo();
private boolean mBatteryLevelCritical;
- private int mLastBatteryStatus;
- private int mLastBatteryHealth;
- private boolean mLastBatteryPresent;
- private int mLastBatteryLevel;
- private int mLastBatteryVoltage;
- private int mLastBatteryTemperature;
- private boolean mLastBatteryLevelCritical;
- private int mLastMaxChargingCurrent;
- private int mLastMaxChargingVoltage;
- private int mLastChargeCounter;
- private int mLastBatteryCycleCount;
- private int mLastChargingState;
- private int mLastBatteryCapacityLevel;
+
+ /**
+ * {@link HealthInfo#batteryStatus} value when {@link Intent#ACTION_BATTERY_CHANGED}
+ * broadcast was sent last.
+ * Note: This value may be used for internal operations and/or to determine whether to trigger
+ * the {@link Intent#ACTION_BATTERY_CHANGED} broadcast or not.
+ */
+ private int mLastBroadcastBatteryStatus;
+ /**
+ * {@link HealthInfo#batteryHealth} value when {@link Intent#ACTION_BATTERY_CHANGED}
+ * broadcast was sent last.
+ * Note: This value may be used for internal operations and/or to determine whether to trigger
+ * the {@link Intent#ACTION_BATTERY_CHANGED} broadcast or not.
+ */
+ private int mLastBroadcastBatteryHealth;
+ /**
+ * {@link HealthInfo#batteryPresent} value when {@link Intent#ACTION_BATTERY_CHANGED}
+ * broadcast was sent last.
+ * Note: This value may be used for internal operations and/or to determine whether to trigger
+ * the {@link Intent#ACTION_BATTERY_CHANGED} broadcast or not.
+ */
+ private boolean mLastBroadcastBatteryPresent;
+ /**
+ * {@link HealthInfo#batteryLevel} value when {@link Intent#ACTION_BATTERY_CHANGED}
+ * broadcast was sent last.
+ * Note: This value may be used for internal operations and/or to determine whether to trigger
+ * the {@link Intent#ACTION_BATTERY_CHANGED} broadcast or not.
+ */
+ private int mLastBroadcastBatteryLevel;
+ /**
+ * {@link HealthInfo#batteryVoltageMillivolts} value when {@link Intent#ACTION_BATTERY_CHANGED}
+ * broadcast was sent last.
+ * Note: This value may be used for internal operations and/or to determine whether to trigger
+ * the {@link Intent#ACTION_BATTERY_CHANGED} broadcast or not.
+ */
+ private int mLastBroadcastBatteryVoltage;
+ /**
+ * {@link HealthInfo#batteryTemperatureTenthsCelsius} value when
+ * {@link Intent#ACTION_BATTERY_CHANGED} broadcast was sent last.
+ * Note: This value may be used for internal operations and/or to determine whether to trigger
+ * the {@link Intent#ACTION_BATTERY_CHANGED} broadcast or not.
+ */
+ private int mLastBroadcastBatteryTemperature;
+ /**
+ * {@link #mBatteryLevelCritical} value when {@link Intent#ACTION_BATTERY_CHANGED}
+ * broadcast was sent last.
+ * Note: These values may be used for internal operations and/or to determine whether to trigger
+ * the broadcast or not.
+ */
+ private boolean mLastBroadcastBatteryLevelCritical;
+ /**
+ * {@link HealthInfo#maxChargingCurrentMicroamps} value when
+ * {@link Intent#ACTION_BATTERY_CHANGED} broadcast was sent last.
+ * Note: This value may be used for internal operations and/or to determine whether to trigger
+ * the {@link Intent#ACTION_BATTERY_CHANGED} broadcast or not.
+ */
+ private int mLastBroadcastMaxChargingCurrent;
+ /**
+ * {@link HealthInfo#maxChargingVoltageMicrovolts} value when
+ * {@link Intent#ACTION_BATTERY_CHANGED} broadcast was sent last.
+ * Note: This value may be used for internal operations and/or to determine whether to trigger
+ * the {@link Intent#ACTION_BATTERY_CHANGED} broadcast or not.
+ */
+ private int mLastBroadcastMaxChargingVoltage;
+ /**
+ * {@link HealthInfo#batteryChargeCounterUah} value when {@link Intent#ACTION_BATTERY_CHANGED}
+ * broadcast was sent last.
+ * Note: This value may be used for internal operations and/or to determine whether to trigger
+ * the {@link Intent#ACTION_BATTERY_CHANGED} broadcast or not.
+ */
+ private int mLastBroadcastChargeCounter;
+ /**
+ * {@link HealthInfo#batteryCycleCount} value when {@link Intent#ACTION_BATTERY_CHANGED}
+ * broadcast was sent last.
+ * Note: This value may be used for internal operations and/or to determine whether to trigger
+ * the {@link Intent#ACTION_BATTERY_CHANGED} broadcast or not.
+ */
+ private int mLastBroadcastBatteryCycleCount;
+ /**
+ * {@link HealthInfo#chargingState} value when {@link Intent#ACTION_BATTERY_CHANGED}
+ * broadcast was sent last.
+ * Note: This value may be used for internal operations and/or to determine whether to trigger
+ * the {@link Intent#ACTION_BATTERY_CHANGED} broadcast or not.
+ */
+ private int mLastBroadcastChargingState;
+ /**
+ * {@link HealthInfo#batteryCapacityLevel} value when {@link Intent#ACTION_BATTERY_CHANGED}
+ * broadcast was sent last.
+ * Note: This value may be used for internal operations and/or to determine whether to trigger
+ * the {@link Intent#ACTION_BATTERY_CHANGED} broadcast or not.
+ */
+ private int mLastBroadcastBatteryCapacityLevel;
+ /**
+ * {@link #mPlugType} value when {@link Intent#ACTION_BATTERY_CHANGED}
+ * broadcast was sent last.
+ * Note: These values may be used for internal operations and/or to determine whether to trigger
+ * the broadcast or not.
+ */
+ private int mLastBroadcastPlugType = -1; // Extra state so we can detect first run
+ /**
+ * {@link #mInvalidCharger} value when {@link Intent#ACTION_BATTERY_CHANGED}
+ * broadcast was sent last.
+ * Note: These values may be used for internal operations and/or to determine whether to trigger
+ * the broadcast or not.
+ */
+ private int mLastBroadcastInvalidCharger;
/**
* The last seen charging policy. This requires the
* {@link android.Manifest.permission#BATTERY_STATS} permission and should therefore not be
@@ -172,7 +271,6 @@
private int mSequence = 1;
private int mInvalidCharger;
- private int mLastInvalidCharger;
private int mLowBatteryWarningLevel;
private int mLastLowBatteryWarningLevel;
@@ -184,7 +282,6 @@
private static String sSystemUiPackage;
private int mPlugType;
- private int mLastPlugType = -1; // Extra state so we can detect first run
private boolean mBatteryLevelLow;
@@ -197,6 +294,16 @@
private boolean mUpdatesStopped;
private boolean mBatteryInputSuspended;
+ /**
+ * Time when the voltage was updated last by HAL and we sent the
+ * {@link Intent#ACTION_BATTERY_CHANGED} broadcast.
+ * Note: This value is used to rate limit the {@link Intent#ACTION_BATTERY_CHANGED} broadcast
+ * so it is possible that voltage was updated but we did not send the broadcast so in that
+ * case we do not update the time.
+ */
+ @VisibleForTesting
+ public long mLastBroadcastVoltageUpdateTime;
+
private Led mLed;
private boolean mSentLowBatteryBroadcast = false;
@@ -211,7 +318,8 @@
private final CopyOnWriteArraySet<BatteryManagerInternal.ChargingPolicyChangeListener>
mChargingPolicyChangeListeners = new CopyOnWriteArraySet<>();
- private static final Bundle BATTERY_CHANGED_OPTIONS = BroadcastOptions.makeBasic()
+ @VisibleForTesting
+ public static final Bundle BATTERY_CHANGED_OPTIONS = BroadcastOptions.makeBasic()
.setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT)
.setDeferralPolicy(BroadcastOptions.DEFERRAL_POLICY_UNTIL_ACTIVE)
.toBundle();
@@ -234,6 +342,25 @@
private static final int MSG_BROADCAST_POWER_CONNECTION_CHANGED = 2;
private static final int MSG_BROADCAST_BATTERY_LOW_OKAY = 3;
+ /**
+ * This value is used to rate limit the {@link Intent#ACTION_BATTERY_CHANGED} broadcast. We
+ * only send the broadcast and update the temperature value when the temp change is greater or
+ * equals to 1 degree celsius.
+ */
+ private static final int ABSOLUTE_DECI_CELSIUS_DIFF_FOR_TEMP_UPDATE = 10;
+ /**
+ * This value is used to rate limit the {@link Intent#ACTION_BATTERY_CHANGED} broadcast. We
+ * only send the broadcast if the last voltage was updated at least 20s seconds back and has a
+ * fluctuation of at least 1%.
+ */
+ private static final int TIME_DIFF_FOR_VOLTAGE_UPDATE_MS = 20000;
+ /**
+ * The value is used to rate limit the {@link Intent#ACTION_BATTERY_CHANGED} broadcast. We
+ * only send the broadcast if the last voltage was updated at least 20s seconds back and has a
+ * fluctuation of at least 1%.
+ */
+ private static final float BASE_POINT_DIFF_FOR_VOLTAGE_UPDATE = 0.01f;
+
private final Handler.Callback mLocalCallback = msg -> {
switch (msg.what) {
case MSG_BROADCAST_BATTERY_CHANGED: {
@@ -283,10 +410,19 @@
};
public BatteryService(Context context) {
+ this(context, Objects.requireNonNull(Looper.myLooper(),
+ "BatteryService uses handler!! Can't create handler inside thread that has not "
+ + "called Looper.prepare()"));
+ }
+
+ @VisibleForTesting
+ public BatteryService(Context context, @NonNull Looper looper) {
super(context);
+ Objects.requireNonNull(looper);
+
mContext = context;
- mHandler = new Handler(mLocalCallback, true /*async*/);
+ mHandler = new Handler(looper, mLocalCallback, true /*async*/);
mLed = new Led(context, getLocalService(LightsManager.class));
mBatteryStats = BatteryStatsService.getService();
mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
@@ -436,7 +572,7 @@
private boolean shouldSendBatteryLowLocked() {
final boolean plugged = mPlugType != BATTERY_PLUGGED_NONE;
- final boolean oldPlugged = mLastPlugType != BATTERY_PLUGGED_NONE;
+ final boolean oldPlugged = mLastBroadcastPlugType != BATTERY_PLUGGED_NONE;
/* The ACTION_BATTERY_LOW broadcast is sent in these situations:
* - is just un-plugged (previously was plugged) and battery level is
@@ -447,7 +583,7 @@
return !plugged
&& mHealthInfo.batteryStatus != BatteryManager.BATTERY_STATUS_UNKNOWN
&& mHealthInfo.batteryLevel <= mLowBatteryWarningLevel
- && (oldPlugged || mLastBatteryLevel > mLowBatteryWarningLevel
+ && (oldPlugged || mLastBroadcastBatteryLevel > mLowBatteryWarningLevel
|| mHealthInfo.batteryLevel > mLastLowBatteryWarningLevel);
}
@@ -515,7 +651,13 @@
}
}
- private void update(android.hardware.health.HealthInfo info) {
+ /**
+ * Updates the healthInfo and triggers the broadcast.
+ *
+ * @param info the new health info
+ */
+ @VisibleForTesting
+ public void update(android.hardware.health.HealthInfo info) {
traceBegin("HealthInfoUpdate");
Trace.traceCounter(
@@ -556,8 +698,8 @@
long dischargeDuration = 0;
mBatteryLevelCritical =
- mHealthInfo.batteryStatus != BatteryManager.BATTERY_STATUS_UNKNOWN
- && mHealthInfo.batteryLevel <= mCriticalBatteryLevel;
+ mHealthInfo.batteryStatus != BatteryManager.BATTERY_STATUS_UNKNOWN
+ && mHealthInfo.batteryLevel <= mCriticalBatteryLevel;
mPlugType = plugType(mHealthInfo);
if (DEBUG) {
@@ -591,24 +733,28 @@
mHandler.post(this::notifyChargingPolicyChanged);
}
- if (force
- || (mHealthInfo.batteryStatus != mLastBatteryStatus
- || mHealthInfo.batteryHealth != mLastBatteryHealth
- || mHealthInfo.batteryPresent != mLastBatteryPresent
- || mHealthInfo.batteryLevel != mLastBatteryLevel
- || mPlugType != mLastPlugType
- || mHealthInfo.batteryVoltageMillivolts != mLastBatteryVoltage
- || mHealthInfo.batteryTemperatureTenthsCelsius != mLastBatteryTemperature
- || mHealthInfo.maxChargingCurrentMicroamps != mLastMaxChargingCurrent
- || mHealthInfo.maxChargingVoltageMicrovolts != mLastMaxChargingVoltage
- || mHealthInfo.batteryChargeCounterUah != mLastChargeCounter
- || mInvalidCharger != mLastInvalidCharger
- || mHealthInfo.batteryCycleCount != mLastBatteryCycleCount
- || mHealthInfo.chargingState != mLastChargingState
- || mHealthInfo.batteryCapacityLevel != mLastBatteryCapacityLevel)) {
+ final boolean includeChargeCounter =
+ !com.android.server.flags.Flags.rateLimitBatteryChangedBroadcast()
+ && mHealthInfo.batteryChargeCounterUah != mLastBroadcastChargeCounter;
- if (mPlugType != mLastPlugType) {
- if (mLastPlugType == BATTERY_PLUGGED_NONE) {
+ if (force
+ || (mHealthInfo.batteryStatus != mLastBroadcastBatteryStatus
+ || mHealthInfo.batteryHealth != mLastBroadcastBatteryHealth
+ || mHealthInfo.batteryPresent != mLastBroadcastBatteryPresent
+ || mHealthInfo.batteryLevel != mLastBroadcastBatteryLevel
+ || mPlugType != mLastBroadcastPlugType
+ || mHealthInfo.batteryVoltageMillivolts != mLastBroadcastBatteryVoltage
+ || mHealthInfo.batteryTemperatureTenthsCelsius != mLastBroadcastBatteryTemperature
+ || mHealthInfo.maxChargingCurrentMicroamps != mLastBroadcastMaxChargingCurrent
+ || mHealthInfo.maxChargingVoltageMicrovolts != mLastBroadcastMaxChargingVoltage
+ || includeChargeCounter
+ || mInvalidCharger != mLastBroadcastInvalidCharger
+ || mHealthInfo.batteryCycleCount != mLastBroadcastBatteryCycleCount
+ || mHealthInfo.chargingState != mLastBroadcastChargingState
+ || mHealthInfo.batteryCapacityLevel != mLastBroadcastBatteryCapacityLevel)) {
+
+ if (mPlugType != mLastBroadcastPlugType) {
+ if (mLastBroadcastPlugType == BATTERY_PLUGGED_NONE) {
// discharging -> charging
mChargeStartLevel = mHealthInfo.batteryLevel;
mChargeStartTime = SystemClock.elapsedRealtime();
@@ -622,7 +768,8 @@
// There's no value in this data unless we've discharged at least once and the
// battery level has changed; so don't log until it does.
- if (mDischargeStartTime != 0 && mDischargeStartLevel != mHealthInfo.batteryLevel) {
+ if (mDischargeStartTime != 0
+ && mDischargeStartLevel != mHealthInfo.batteryLevel) {
dischargeDuration = SystemClock.elapsedRealtime() - mDischargeStartTime;
logOutlier = true;
EventLog.writeEvent(EventLogTags.BATTERY_DISCHARGE, dischargeDuration,
@@ -639,7 +786,7 @@
if (mChargeStartTime != 0 && chargeDuration != 0) {
final LogMaker builder = new LogMaker(MetricsEvent.ACTION_CHARGE);
builder.setType(MetricsEvent.TYPE_DISMISS);
- builder.addTaggedData(MetricsEvent.FIELD_PLUG_TYPE, mLastPlugType);
+ builder.addTaggedData(MetricsEvent.FIELD_PLUG_TYPE, mLastBroadcastPlugType);
builder.addTaggedData(MetricsEvent.FIELD_CHARGING_DURATION_MILLIS,
chargeDuration);
builder.addTaggedData(MetricsEvent.FIELD_BATTERY_LEVEL_START,
@@ -651,19 +798,20 @@
mChargeStartTime = 0;
}
}
- if (mHealthInfo.batteryStatus != mLastBatteryStatus ||
- mHealthInfo.batteryHealth != mLastBatteryHealth ||
- mHealthInfo.batteryPresent != mLastBatteryPresent ||
- mPlugType != mLastPlugType) {
+ if (mHealthInfo.batteryStatus != mLastBroadcastBatteryStatus
+ || mHealthInfo.batteryHealth != mLastBroadcastBatteryHealth
+ || mHealthInfo.batteryPresent != mLastBroadcastBatteryPresent
+ || mPlugType != mLastBroadcastPlugType) {
EventLog.writeEvent(EventLogTags.BATTERY_STATUS,
- mHealthInfo.batteryStatus, mHealthInfo.batteryHealth, mHealthInfo.batteryPresent ? 1 : 0,
+ mHealthInfo.batteryStatus, mHealthInfo.batteryHealth,
+ mHealthInfo.batteryPresent ? 1 : 0,
mPlugType, mHealthInfo.batteryTechnology);
SystemProperties.set(
"debug.tracing.battery_status",
Integer.toString(mHealthInfo.batteryStatus));
SystemProperties.set("debug.tracing.plug_type", Integer.toString(mPlugType));
}
- if (mHealthInfo.batteryLevel != mLastBatteryLevel) {
+ if (mHealthInfo.batteryLevel != mLastBroadcastBatteryLevel) {
// Don't do this just from voltage or temperature changes, that is
// too noisy.
EventLog.writeEvent(
@@ -672,8 +820,8 @@
mHealthInfo.batteryVoltageMillivolts,
mHealthInfo.batteryTemperatureTenthsCelsius);
}
- if (mBatteryLevelCritical && !mLastBatteryLevelCritical &&
- mPlugType == BATTERY_PLUGGED_NONE) {
+ if (mBatteryLevelCritical && !mLastBroadcastBatteryLevelCritical
+ && mPlugType == BATTERY_PLUGGED_NONE) {
// We want to make sure we log discharge cycle outliers
// if the battery is about to die.
dischargeDuration = SystemClock.elapsedRealtime() - mDischargeStartTime;
@@ -684,7 +832,7 @@
// Should we now switch in to low battery mode?
if (mPlugType == BATTERY_PLUGGED_NONE
&& mHealthInfo.batteryStatus !=
- BatteryManager.BATTERY_STATUS_UNKNOWN
+ BatteryManager.BATTERY_STATUS_UNKNOWN
&& mHealthInfo.batteryLevel <= mLowBatteryWarningLevel) {
mBatteryLevelLow = true;
}
@@ -692,7 +840,7 @@
// Should we now switch out of low battery mode?
if (mPlugType != BATTERY_PLUGGED_NONE) {
mBatteryLevelLow = false;
- } else if (mHealthInfo.batteryLevel >= mLowBatteryCloseWarningLevel) {
+ } else if (mHealthInfo.batteryLevel >= mLowBatteryCloseWarningLevel) {
mBatteryLevelLow = false;
} else if (force && mHealthInfo.batteryLevel >= mLowBatteryWarningLevel) {
// If being forced, the previous state doesn't matter, we will just
@@ -706,7 +854,7 @@
// Separate broadcast is sent for power connected / not connected
// since the standard intent will not wake any applications and some
// applications may want to have smart behavior based on this.
- if (mPlugType != 0 && mLastPlugType == 0) {
+ if (mPlugType != 0 && mLastBroadcastPlugType == 0) {
final Intent statusIntent = new Intent(Intent.ACTION_POWER_CONNECTED);
statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
statusIntent.putExtra(BatteryManager.EXTRA_SEQUENCE, mSequence);
@@ -726,8 +874,7 @@
}
});
}
- }
- else if (mPlugType == 0 && mLastPlugType != 0) {
+ } else if (mPlugType == 0 && mLastBroadcastPlugType != 0) {
final Intent statusIntent = new Intent(Intent.ACTION_POWER_DISCONNECTED);
statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
statusIntent.putExtra(BatteryManager.EXTRA_SEQUENCE, mSequence);
@@ -797,8 +944,14 @@
// We are doing this after sending the above broadcasts, so anything processing
// them will get the new sequence number at that point. (See for example how testing
// of JobScheduler's BatteryController works.)
- sendBatteryChangedIntentLocked(force);
- if (mLastBatteryLevel != mHealthInfo.batteryLevel || mLastPlugType != mPlugType) {
+
+ boolean rateLimitBatteryChangedBroadcast = rateLimitBatteryChangedBroadcast(force);
+
+ if (!rateLimitBatteryChangedBroadcast) {
+ sendBatteryChangedIntentLocked(force);
+ }
+ if (mLastBroadcastBatteryLevel != mHealthInfo.batteryLevel
+ || mLastBroadcastPlugType != mPlugType) {
sendBatteryLevelChangedIntentLocked();
}
@@ -811,21 +964,24 @@
logOutlierLocked(dischargeDuration);
}
- mLastBatteryStatus = mHealthInfo.batteryStatus;
- mLastBatteryHealth = mHealthInfo.batteryHealth;
- mLastBatteryPresent = mHealthInfo.batteryPresent;
- mLastBatteryLevel = mHealthInfo.batteryLevel;
- mLastPlugType = mPlugType;
- mLastBatteryVoltage = mHealthInfo.batteryVoltageMillivolts;
- mLastBatteryTemperature = mHealthInfo.batteryTemperatureTenthsCelsius;
- mLastMaxChargingCurrent = mHealthInfo.maxChargingCurrentMicroamps;
- mLastMaxChargingVoltage = mHealthInfo.maxChargingVoltageMicrovolts;
- mLastChargeCounter = mHealthInfo.batteryChargeCounterUah;
- mLastBatteryLevelCritical = mBatteryLevelCritical;
- mLastInvalidCharger = mInvalidCharger;
- mLastBatteryCycleCount = mHealthInfo.batteryCycleCount;
- mLastChargingState = mHealthInfo.chargingState;
- mLastBatteryCapacityLevel = mHealthInfo.batteryCapacityLevel;
+ // Only update the values when we send the broadcast
+ if (!rateLimitBatteryChangedBroadcast) {
+ mLastBroadcastBatteryStatus = mHealthInfo.batteryStatus;
+ mLastBroadcastBatteryHealth = mHealthInfo.batteryHealth;
+ mLastBroadcastBatteryPresent = mHealthInfo.batteryPresent;
+ mLastBroadcastBatteryLevel = mHealthInfo.batteryLevel;
+ mLastBroadcastPlugType = mPlugType;
+ mLastBroadcastBatteryVoltage = mHealthInfo.batteryVoltageMillivolts;
+ mLastBroadcastBatteryTemperature = mHealthInfo.batteryTemperatureTenthsCelsius;
+ mLastBroadcastMaxChargingCurrent = mHealthInfo.maxChargingCurrentMicroamps;
+ mLastBroadcastMaxChargingVoltage = mHealthInfo.maxChargingVoltageMicrovolts;
+ mLastBroadcastChargeCounter = mHealthInfo.batteryChargeCounterUah;
+ mLastBroadcastBatteryLevelCritical = mBatteryLevelCritical;
+ mLastBroadcastInvalidCharger = mInvalidCharger;
+ mLastBroadcastBatteryCycleCount = mHealthInfo.batteryCycleCount;
+ mLastBroadcastChargingState = mHealthInfo.chargingState;
+ mLastBroadcastBatteryCapacityLevel = mHealthInfo.batteryCapacityLevel;
+ }
}
}
@@ -1089,6 +1245,74 @@
}
}
+ /**
+ * Rate limit's the broadcast based on the changes in temp, voltage and chargeCounter.
+ */
+ private boolean rateLimitBatteryChangedBroadcast(boolean forceUpdate) {
+ if (!com.android.server.flags.Flags.rateLimitBatteryChangedBroadcast()) {
+ return false;
+ }
+ if (mLastBroadcastBatteryVoltage == 0 || mLastBroadcastBatteryTemperature == 0) {
+ mLastBroadcastVoltageUpdateTime = SystemClock.elapsedRealtime();
+ return false;
+ }
+
+ final boolean voltageUpdated =
+ mLastBroadcastBatteryVoltage != mHealthInfo.batteryVoltageMillivolts;
+ final boolean temperatureUpdated =
+ mLastBroadcastBatteryTemperature != mHealthInfo.batteryTemperatureTenthsCelsius;
+ final boolean otherStatesUpdated = forceUpdate
+ || mHealthInfo.batteryStatus != mLastBroadcastBatteryStatus
+ || mHealthInfo.batteryHealth != mLastBroadcastBatteryHealth
+ || mHealthInfo.batteryPresent != mLastBroadcastBatteryPresent
+ || mHealthInfo.batteryLevel != mLastBroadcastBatteryLevel
+ || mPlugType != mLastBroadcastPlugType
+ || mHealthInfo.maxChargingCurrentMicroamps != mLastBroadcastMaxChargingCurrent
+ || mHealthInfo.maxChargingVoltageMicrovolts != mLastBroadcastMaxChargingVoltage
+ || mInvalidCharger != mLastBroadcastInvalidCharger
+ || mHealthInfo.batteryCycleCount != mLastBroadcastBatteryCycleCount
+ || mHealthInfo.chargingState != mLastBroadcastChargingState
+ || mHealthInfo.batteryCapacityLevel != mLastBroadcastBatteryCapacityLevel;
+
+ // We only rate limit based on changes in the temp, voltage.
+ if (otherStatesUpdated) {
+
+ if (voltageUpdated) {
+ mLastBroadcastVoltageUpdateTime = SystemClock.elapsedRealtime();
+ }
+ return false;
+ }
+
+ final float basePointDiff =
+ (float) (mLastBroadcastBatteryVoltage - mHealthInfo.batteryVoltageMillivolts)
+ / mLastBroadcastBatteryVoltage;
+
+ // We only send the broadcast if voltage change is greater than 1% and last voltage
+ // update was sent at least 20 seconds back.
+ if (voltageUpdated
+ && abs(basePointDiff) >= BASE_POINT_DIFF_FOR_VOLTAGE_UPDATE
+ && SystemClock.elapsedRealtime() - mLastBroadcastVoltageUpdateTime
+ >= TIME_DIFF_FOR_VOLTAGE_UPDATE_MS) {
+ mLastBroadcastVoltageUpdateTime = SystemClock.elapsedRealtime();
+
+ return false;
+ }
+
+ // Only send the broadcast if the temperature update is greater than 1 degree celsius.
+ if (temperatureUpdated
+ && abs(
+ mLastBroadcastBatteryTemperature - mHealthInfo.batteryTemperatureTenthsCelsius)
+ >= ABSOLUTE_DECI_CELSIUS_DIFF_FOR_TEMP_UPDATE) {
+
+ if (voltageUpdated) {
+ mLastBroadcastVoltageUpdateTime = SystemClock.elapsedRealtime();
+ }
+ return false;
+ }
+
+ return true;
+ }
+
class Shell extends ShellCommand {
@Override
public int onCommand(String cmd) {
@@ -1399,6 +1623,10 @@
pw.println(" level: " + mHealthInfo.batteryLevel);
pw.println(" scale: " + BATTERY_SCALE);
pw.println(" voltage: " + mHealthInfo.batteryVoltageMillivolts);
+ pw.println(" Time when the latest updated value of the voltage was sent via "
+ + "battery changed broadcast: " + mLastBroadcastVoltageUpdateTime);
+ pw.println(" The last voltage value sent via the battery changed broadcast: "
+ + mLastBroadcastBatteryVoltage);
pw.println(" temperature: " + mHealthInfo.batteryTemperatureTenthsCelsius);
pw.println(" technology: " + mHealthInfo.batteryTechnology);
pw.println(" Charging state: " + mHealthInfo.chargingState);
@@ -1457,6 +1685,11 @@
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
+ @VisibleForTesting
+ public Handler getHandlerForTest() {
+ return mHandler;
+ }
+
@SuppressLint("AndroidFrameworkRequiresPermission")
private static void sendBroadcastToAllUsers(Context context, Intent intent,
Bundle options) {
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 08632fe..c067662 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -514,27 +514,11 @@
mLogger = new OomAdjusterDebugLogger(this, mService.mConstants);
mProcessGroupHandler = new Handler(adjusterThread.getLooper(), msg -> {
- final int pid = msg.arg1;
- final int group = msg.arg2;
- if (pid == ActivityManagerService.MY_PID) {
- // Skip setting the process group for system_server, keep it as default.
- return true;
- }
- final boolean traceEnabled = Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER);
- if (traceEnabled) {
- Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "setProcessGroup "
- + msg.obj + " to " + group);
- }
- try {
- android.os.Process.setProcessGroup(pid, group);
- } catch (Exception e) {
- if (DEBUG_ALL) {
- Slog.w(TAG, "Failed setting process group of " + pid + " to " + group, e);
- }
- } finally {
- if (traceEnabled) {
- Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
- }
+ final int group = msg.what;
+ final ProcessRecord app = (ProcessRecord) msg.obj;
+ setProcessGroup(app.getPid(), group, app.processName);
+ if (Flags.phantomProcessesFix()) {
+ mService.mPhantomProcessList.setProcessGroupForPhantomProcessOfApp(app, group);
}
return true;
});
@@ -545,8 +529,31 @@
}
void setProcessGroup(int pid, int group, String processName) {
+ if (pid == ActivityManagerService.MY_PID) {
+ // Skip setting the process group for system_server, keep it as default.
+ return;
+ }
+ final boolean traceEnabled = Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+ if (traceEnabled) {
+ Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "setProcessGroup "
+ + processName + " to " + group);
+ }
+ try {
+ android.os.Process.setProcessGroup(pid, group);
+ } catch (Exception e) {
+ if (DEBUG_ALL) {
+ Slog.w(TAG, "Failed setting process group of " + pid + " to " + group, e);
+ }
+ } finally {
+ if (traceEnabled) {
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+ }
+ }
+ }
+
+ void setAppAndChildProcessGroup(ProcessRecord app, int group) {
mProcessGroupHandler.sendMessage(mProcessGroupHandler.obtainMessage(
- 0 /* unused */, pid, group, processName));
+ group, app));
}
void initSettings() {
@@ -3503,8 +3510,7 @@
processGroup = THREAD_GROUP_DEFAULT;
break;
}
- setProcessGroup(app.getPid(), processGroup, app.processName);
- mService.mPhantomProcessList.setProcessGroupForPhantomProcessOfApp(app, processGroup);
+ setAppAndChildProcessGroup(app, processGroup);
try {
final int renderThreadTid = app.getRenderThreadTid();
if (curSchedGroup == SCHED_GROUP_TOP_APP) {
diff --git a/services/core/java/com/android/server/am/PhantomProcessList.java b/services/core/java/com/android/server/am/PhantomProcessList.java
index bfdced7..123780f 100644
--- a/services/core/java/com/android/server/am/PhantomProcessList.java
+++ b/services/core/java/com/android/server/am/PhantomProcessList.java
@@ -548,6 +548,7 @@
*/
void setProcessGroupForPhantomProcessOfApp(final ProcessRecord app, final int group) {
synchronized (mLock) {
+ lookForPhantomProcessesLocked(app);
final SparseArray<PhantomProcessRecord> array = getPhantomProcessOfAppLocked(app);
if (array == null) {
return;
diff --git a/services/core/java/com/android/server/am/flags.aconfig b/services/core/java/com/android/server/am/flags.aconfig
index 7b4d6c7..5d5b35b 100644
--- a/services/core/java/com/android/server/am/flags.aconfig
+++ b/services/core/java/com/android/server/am/flags.aconfig
@@ -250,4 +250,14 @@
is_fixed_read_only: true
description: "Add +X to the prev scores according to their positions in the process LRU list"
bug: "359912586"
-}
\ No newline at end of file
+}
+
+flag {
+ name: "phantom_processes_fix"
+ namespace: "backstage_power"
+ description: "Make sure setProcessGroupForPhantomProcessOfApp deals with phantom processes properly"
+ bug: "375058190"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index f5a75c7d..0e77040 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -25,7 +25,7 @@
import static android.Manifest.permission.RESTRICT_DISPLAY_MODES;
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED;
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE;
-import static android.hardware.display.DisplayManager.EventFlag;
+import static android.hardware.display.DisplayManagerGlobal.InternalEventFlag;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
@@ -1390,16 +1390,16 @@
}
private void registerCallbackInternal(IDisplayManagerCallback callback, int callingPid,
- int callingUid, @EventFlag long eventFlagsMask) {
+ int callingUid, @InternalEventFlag long internalEventFlagsMask) {
synchronized (mSyncRoot) {
CallbackRecord record = mCallbacks.get(callingPid);
if (record != null) {
- record.updateEventFlagsMask(eventFlagsMask);
+ record.updateEventFlagsMask(internalEventFlagsMask);
return;
}
- record = new CallbackRecord(callingPid, callingUid, callback, eventFlagsMask);
+ record = new CallbackRecord(callingPid, callingUid, callback, internalEventFlagsMask);
try {
IBinder binder = callback.asBinder();
binder.linkToDeath(record, 0);
@@ -4009,7 +4009,7 @@
public final int mPid;
public final int mUid;
private final IDisplayManagerCallback mCallback;
- private @DisplayManager.EventFlag AtomicLong mEventFlagsMask;
+ private @InternalEventFlag AtomicLong mInternalEventFlagsMask;
private final String mPackageName;
public boolean mWifiDisplayScanRequested;
@@ -4030,11 +4030,11 @@
private boolean mFrozen;
CallbackRecord(int pid, int uid, @NonNull IDisplayManagerCallback callback,
- @EventFlag long eventFlagsMask) {
+ @InternalEventFlag long internalEventFlagsMask) {
mPid = pid;
mUid = uid;
mCallback = callback;
- mEventFlagsMask = new AtomicLong(eventFlagsMask);
+ mInternalEventFlagsMask = new AtomicLong(internalEventFlagsMask);
mCached = false;
mFrozen = false;
@@ -4056,8 +4056,8 @@
mPackageName = packageNames == null ? null : packageNames[0];
}
- public void updateEventFlagsMask(@EventFlag long eventFlag) {
- mEventFlagsMask.set(eventFlag);
+ public void updateEventFlagsMask(@InternalEventFlag long internalEventFlag) {
+ mInternalEventFlagsMask.set(internalEventFlag);
}
/**
@@ -4121,13 +4121,13 @@
if (!shouldSendEvent(event)) {
if (extraLogging(mPackageName)) {
Slog.i(TAG,
- "Not sending displayEvent: " + event + " due to flag:"
- + mEventFlagsMask);
+ "Not sending displayEvent: " + event + " due to mask:"
+ + mInternalEventFlagsMask);
}
if (Trace.isTagEnabled(Trace.TRACE_TAG_POWER)) {
Trace.instant(Trace.TRACE_TAG_POWER,
- "notifyDisplayEventAsync#notSendingEvent=" + event + ",mEventsFlag="
- + mEventFlagsMask);
+ "notifyDisplayEventAsync#notSendingEvent=" + event
+ + ",mInternalEventFlagsMask=" + mInternalEventFlagsMask);
}
// The client is not interested in this event, so do nothing.
return true;
@@ -4173,22 +4173,29 @@
* Return true if the client is interested in this event.
*/
private boolean shouldSendEvent(@DisplayEvent int event) {
- final long flag = mEventFlagsMask.get();
+ final long mask = mInternalEventFlagsMask.get();
switch (event) {
case DisplayManagerGlobal.EVENT_DISPLAY_ADDED:
- return (flag & DisplayManager.EVENT_FLAG_DISPLAY_ADDED) != 0;
+ return (mask & DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_ADDED) != 0;
case DisplayManagerGlobal.EVENT_DISPLAY_CHANGED:
- return (flag & DisplayManager.EVENT_FLAG_DISPLAY_CHANGED) != 0;
+ return (mask & DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_CHANGED) != 0;
case DisplayManagerGlobal.EVENT_DISPLAY_BRIGHTNESS_CHANGED:
- return (flag & DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS) != 0;
+ return (mask
+ & DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_BRIGHTNESS_CHANGED)
+ != 0;
case DisplayManagerGlobal.EVENT_DISPLAY_REMOVED:
- return (flag & DisplayManager.EVENT_FLAG_DISPLAY_REMOVED) != 0;
+ return (mask & DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_REMOVED) != 0;
case DisplayManagerGlobal.EVENT_DISPLAY_HDR_SDR_RATIO_CHANGED:
- return (flag & DisplayManager.EVENT_FLAG_HDR_SDR_RATIO_CHANGED) != 0;
+ return (mask
+ & DisplayManagerGlobal
+ .INTERNAL_EVENT_FLAG_DISPLAY_HDR_SDR_RATIO_CHANGED)
+ != 0;
case DisplayManagerGlobal.EVENT_DISPLAY_CONNECTED:
// fallthrough
case DisplayManagerGlobal.EVENT_DISPLAY_DISCONNECTED:
- return (flag & DisplayManager.EVENT_FLAG_DISPLAY_CONNECTION_CHANGED) != 0;
+ return (mask
+ & DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_CONNECTION_CHANGED)
+ != 0;
default:
// This should never happen.
Slog.e(TAG, "Unknown display event " + event);
@@ -4374,15 +4381,16 @@
@Override // Binder call
public void registerCallback(IDisplayManagerCallback callback) {
- registerCallbackWithEventMask(callback, DisplayManager.EVENT_FLAG_DISPLAY_ADDED
- | DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
- | DisplayManager.EVENT_FLAG_DISPLAY_REMOVED);
+ registerCallbackWithEventMask(callback,
+ DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_ADDED
+ | DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_CHANGED
+ | DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_REMOVED);
}
@Override // Binder call
@SuppressLint("AndroidFrameworkRequiresPermission") // Permission only required sometimes
public void registerCallbackWithEventMask(IDisplayManagerCallback callback,
- @EventFlag long eventFlagsMask) {
+ @InternalEventFlag long internalEventFlagsMask) {
if (callback == null) {
throw new IllegalArgumentException("listener must not be null");
}
@@ -4391,7 +4399,9 @@
final int callingUid = Binder.getCallingUid();
if (mFlags.isConnectedDisplayManagementEnabled()) {
- if ((eventFlagsMask & DisplayManager.EVENT_FLAG_DISPLAY_CONNECTION_CHANGED) != 0) {
+ if ((internalEventFlagsMask
+ & DisplayManagerGlobal
+ .INTERNAL_EVENT_FLAG_DISPLAY_CONNECTION_CHANGED) != 0) {
mContext.enforceCallingOrSelfPermission(MANAGE_DISPLAYS,
"Permission required to get signals about connection events.");
}
@@ -4399,7 +4409,7 @@
final long token = Binder.clearCallingIdentity();
try {
- registerCallbackInternal(callback, callingPid, callingUid, eventFlagsMask);
+ registerCallbackInternal(callback, callingPid, callingUid, internalEventFlagsMask);
} finally {
Binder.restoreCallingIdentity(token);
}
diff --git a/services/core/java/com/android/server/display/mode/DisplayModeDirector.java b/services/core/java/com/android/server/display/mode/DisplayModeDirector.java
index 88562ab..8423e19 100644
--- a/services/core/java/com/android/server/display/mode/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/mode/DisplayModeDirector.java
@@ -2077,8 +2077,8 @@
mDeviceConfigDisplaySettings.startListening();
mInjector.registerDisplayListener(this, mHandler,
- DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
- | DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS);
+ DisplayManager.EVENT_FLAG_DISPLAY_CHANGED,
+ DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS);
}
private void setLoggingEnabled(boolean loggingEnabled) {
@@ -2878,8 +2878,8 @@
}
mDisplayManagerInternal = mInjector.getDisplayManagerInternal();
mInjector.registerDisplayListener(this, mHandler,
- DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS
- | DisplayManager.EVENT_FLAG_DISPLAY_REMOVED);
+ DisplayManager.EVENT_FLAG_DISPLAY_REMOVED,
+ DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS);
}
/**
@@ -3108,6 +3108,9 @@
void registerDisplayListener(@NonNull DisplayManager.DisplayListener listener,
Handler handler, long flags);
+ void registerDisplayListener(@NonNull DisplayManager.DisplayListener listener,
+ Handler handler, long flags, long privateFlags);
+
Display getDisplay(int displayId);
Display[] getDisplays();
@@ -3175,6 +3178,12 @@
}
@Override
+ public void registerDisplayListener(DisplayManager.DisplayListener listener,
+ Handler handler, long flags, long privateFlags) {
+ getDisplayManager().registerDisplayListener(listener, handler, flags, privateFlags);
+ }
+
+ @Override
public Display getDisplay(int displayId) {
return getDisplayManager().getDisplay(displayId);
}
diff --git a/services/core/java/com/android/server/flags/services.aconfig b/services/core/java/com/android/server/flags/services.aconfig
index 69ba785..eea5c98 100644
--- a/services/core/java/com/android/server/flags/services.aconfig
+++ b/services/core/java/com/android/server/flags/services.aconfig
@@ -67,3 +67,14 @@
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ namespace: "backstage_power"
+ name: "rate_limit_battery_changed_broadcast"
+ description: "Optimize the delivery of the battery changed broadcast by rate limiting the frequency of the updates"
+ bug: "362337621"
+ is_fixed_read_only: true
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 5fc3e33..05bc69a 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -1015,7 +1015,8 @@
permission, attributionSource, message, forDataDelivery, startDataDelivery,
fromDatasource, attributedOp);
// Finish any started op if some step in the attribution chain failed.
- if (startDataDelivery && result != PermissionChecker.PERMISSION_GRANTED) {
+ if (startDataDelivery && result != PermissionChecker.PERMISSION_GRANTED
+ && result != PermissionChecker.PERMISSION_SOFT_DENIED) {
if (attributedOp == AppOpsManager.OP_NONE) {
finishDataDelivery(AppOpsManager.permissionToOpCode(permission),
attributionSource.asState(), fromDatasource);
@@ -1244,6 +1245,7 @@
final boolean hasChain = attributionChainId != ATTRIBUTION_CHAIN_ID_NONE;
AttributionSource current = attributionSource;
AttributionSource next = null;
+ AttributionSource prev = null;
// We consider the chain trusted if the start node has UPDATE_APP_OPS_STATS, and
// every attributionSource in the chain is registered with the system.
final boolean isChainStartTrusted = !hasChain || checkPermission(context,
@@ -1310,6 +1312,22 @@
selfAccess, singleReceiverFromDatasource, attributedOp,
proxyAttributionFlags, proxiedAttributionFlags, attributionChainId);
+ if (startDataDelivery && opMode != AppOpsManager.MODE_ALLOWED) {
+ // Current failed the perm check, so if we are part-way through an attr chain,
+ // we need to clean up the already started proxy op higher up the chain. Note,
+ // proxy ops are verified two by two, which means we have to clear the 2nd next
+ // from the previous iteration (since it is actually curr.next which failed
+ // to pass the perm check).
+ if (prev != null) {
+ final var cutAttrSourceState = prev.asState();
+ if (cutAttrSourceState.next.length > 0) {
+ cutAttrSourceState.next[0].next = new AttributionSourceState[0];
+ }
+ finishDataDelivery(context, attributedOp,
+ cutAttrSourceState, fromDatasource);
+ }
+ }
+
switch (opMode) {
case AppOpsManager.MODE_ERRORED: {
if (permission.equals(Manifest.permission.BLUETOOTH_CONNECT)) {
@@ -1335,6 +1353,8 @@
return PermissionChecker.PERMISSION_GRANTED;
}
+ // an attribution we have already possibly started an op for
+ prev = current;
current = next;
}
}
diff --git a/services/core/java/com/android/server/vcn/VcnContext.java b/services/core/java/com/android/server/vcn/VcnContext.java
index 6ce8685..9213d96 100644
--- a/services/core/java/com/android/server/vcn/VcnContext.java
+++ b/services/core/java/com/android/server/vcn/VcnContext.java
@@ -74,10 +74,6 @@
return mFeatureFlags;
}
- public boolean isFlagSafeModeTimeoutConfigEnabled() {
- return mFeatureFlags.safeModeTimeoutConfig();
- }
-
/**
* Verifies that the caller is running on the VcnContext Thread.
*
diff --git a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
index 2d3bc84..2325f35 100644
--- a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
+++ b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
@@ -1263,7 +1263,7 @@
final PersistableBundleWrapper carrierConfig = snapshot.getCarrierConfigForSubGrp(subGrp);
int resultSeconds = defaultSeconds;
- if (vcnContext.isFlagSafeModeTimeoutConfigEnabled() && carrierConfig != null) {
+ if (carrierConfig != null) {
resultSeconds =
carrierConfig.getInt(
VcnManager.VCN_SAFE_MODE_TIMEOUT_SECONDS_KEY, defaultSeconds);
diff --git a/services/tests/displayservicetests/src/com/android/server/display/BrightnessSynchronizerTest.java b/services/tests/displayservicetests/src/com/android/server/display/BrightnessSynchronizerTest.java
index 06f1b27..a8708f9 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/BrightnessSynchronizerTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/BrightnessSynchronizerTest.java
@@ -223,7 +223,8 @@
mIntRangeUserPerceptionEnabled);
mSynchronizer.startSynchronizing();
verify(mDisplayManagerMock).registerDisplayListener(mDisplayListenerCaptor.capture(),
- isA(Handler.class), eq(DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS));
+ isA(Handler.class), eq(0L),
+ eq(DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS));
mDisplayListener = mDisplayListenerCaptor.getValue();
verify(mContentResolverSpy).registerContentObserver(eq(BRIGHTNESS_URI), eq(false),
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
index b917af4..c741cae 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
@@ -203,11 +203,13 @@
private static final String VIRTUAL_DISPLAY_NAME = "Test Virtual Display";
private static final String PACKAGE_NAME = "com.android.frameworks.displayservicetests";
- private static final long STANDARD_DISPLAY_EVENTS = DisplayManager.EVENT_FLAG_DISPLAY_ADDED
- | DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
- | DisplayManager.EVENT_FLAG_DISPLAY_REMOVED;
+ private static final long STANDARD_DISPLAY_EVENTS =
+ DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_ADDED
+ | DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_CHANGED
+ | DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_REMOVED;
private static final long STANDARD_AND_CONNECTION_DISPLAY_EVENTS =
- STANDARD_DISPLAY_EVENTS | DisplayManager.EVENT_FLAG_DISPLAY_CONNECTION_CHANGED;
+ STANDARD_DISPLAY_EVENTS
+ | DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_CONNECTION_CHANGED;
private static final String EVENT_DISPLAY_ADDED = "EVENT_DISPLAY_ADDED";
private static final String EVENT_DISPLAY_REMOVED = "EVENT_DISPLAY_REMOVED";
@@ -2379,7 +2381,7 @@
// register display listener callback
FakeDisplayManagerCallback callback = new FakeDisplayManagerCallback();
long allEventsExceptDisplayAdded = STANDARD_DISPLAY_EVENTS
- & ~DisplayManager.EVENT_FLAG_DISPLAY_ADDED;
+ & ~DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_ADDED;
displayManagerBinderService.registerCallbackWithEventMask(callback,
allEventsExceptDisplayAdded);
@@ -2450,7 +2452,7 @@
FakeDisplayManagerCallback callback = new FakeDisplayManagerCallback();
long allEventsExceptDisplayRemoved = STANDARD_DISPLAY_EVENTS
- & ~DisplayManager.EVENT_FLAG_DISPLAY_REMOVED;
+ & ~DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_REMOVED;
displayManagerBinderService.registerCallbackWithEventMask(callback,
allEventsExceptDisplayRemoved);
diff --git a/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayModeDirectorTest.java b/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayModeDirectorTest.java
index 58f0ab4..f3fc6d7 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayModeDirectorTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayModeDirectorTest.java
@@ -1225,8 +1225,8 @@
ArgumentCaptor.forClass(DisplayListener.class);
verify(mInjector).registerDisplayListener(displayListenerCaptor.capture(),
any(Handler.class),
- eq(DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
- | DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS));
+ eq(DisplayManager.EVENT_FLAG_DISPLAY_CHANGED),
+ eq(DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS));
DisplayListener displayListener = displayListenerCaptor.getValue();
setBrightness(10, 10, displayListener);
@@ -1256,8 +1256,8 @@
ArgumentCaptor.forClass(DisplayListener.class);
verify(mInjector).registerDisplayListener(displayListenerCaptor.capture(),
any(Handler.class),
- eq(DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
- | DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS));
+ eq(DisplayManager.EVENT_FLAG_DISPLAY_CHANGED),
+ eq(DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS));
DisplayListener displayListener = displayListenerCaptor.getValue();
setBrightness(10, 10, displayListener);
@@ -1291,8 +1291,8 @@
ArgumentCaptor.forClass(DisplayListener.class);
verify(mInjector).registerDisplayListener(displayListenerCaptor.capture(),
any(Handler.class),
- eq(DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
- | DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS));
+ eq(DisplayManager.EVENT_FLAG_DISPLAY_CHANGED),
+ eq(DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS));
DisplayListener displayListener = displayListenerCaptor.getValue();
setBrightness(10, 10, displayListener);
@@ -1325,8 +1325,8 @@
ArgumentCaptor.forClass(DisplayListener.class);
verify(mInjector).registerDisplayListener(displayListenerCaptor.capture(),
any(Handler.class),
- eq(DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
- | DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS));
+ eq(DisplayManager.EVENT_FLAG_DISPLAY_CHANGED),
+ eq(DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS));
DisplayListener displayListener = displayListenerCaptor.getValue();
ArgumentCaptor<SensorEventListener> sensorListenerCaptor =
@@ -1404,8 +1404,8 @@
ArgumentCaptor.forClass(DisplayListener.class);
verify(mInjector).registerDisplayListener(displayListenerCaptor.capture(),
any(Handler.class),
- eq(DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
- | DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS));
+ eq(DisplayManager.EVENT_FLAG_DISPLAY_CHANGED),
+ eq(DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS));
DisplayListener displayListener = displayListenerCaptor.getValue();
ArgumentCaptor<SensorEventListener> sensorListenerCaptor =
@@ -1464,8 +1464,8 @@
ArgumentCaptor.forClass(DisplayListener.class);
verify(mInjector).registerDisplayListener(displayListenerCaptor.capture(),
any(Handler.class),
- eq(DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
- | DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS));
+ eq(DisplayManager.EVENT_FLAG_DISPLAY_CHANGED),
+ eq(DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS));
DisplayListener displayListener = displayListenerCaptor.getValue();
ArgumentCaptor<SensorEventListener> listenerCaptor =
@@ -1630,8 +1630,8 @@
ArgumentCaptor.forClass(DisplayListener.class);
verify(mInjector).registerDisplayListener(displayListenerCaptor.capture(),
any(Handler.class),
- eq(DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
- | DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS));
+ eq(DisplayManager.EVENT_FLAG_DISPLAY_CHANGED),
+ eq(DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS));
DisplayListener displayListener = displayListenerCaptor.getValue();
// Get the sensor listener so that we can give it new light sensor events
@@ -1730,8 +1730,8 @@
ArgumentCaptor.forClass(DisplayListener.class);
verify(mInjector).registerDisplayListener(displayListenerCaptor.capture(),
any(Handler.class),
- eq(DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
- | DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS));
+ eq(DisplayManager.EVENT_FLAG_DISPLAY_CHANGED),
+ eq(DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS));
DisplayListener displayListener = displayListenerCaptor.getValue();
// Get the sensor listener so that we can give it new light sensor events
@@ -2877,8 +2877,8 @@
ArgumentCaptor<DisplayListener> captor =
ArgumentCaptor.forClass(DisplayListener.class);
verify(mInjector).registerDisplayListener(captor.capture(), any(Handler.class),
- eq(DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS
- | DisplayManager.EVENT_FLAG_DISPLAY_REMOVED));
+ eq(DisplayManager.EVENT_FLAG_DISPLAY_REMOVED),
+ eq(DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS));
DisplayListener listener = captor.getValue();
// Specify Limitation
@@ -3000,8 +3000,8 @@
ArgumentCaptor<DisplayListener> captor =
ArgumentCaptor.forClass(DisplayListener.class);
verify(mInjector).registerDisplayListener(captor.capture(), any(Handler.class),
- eq(DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS
- | DisplayManager.EVENT_FLAG_DISPLAY_REMOVED));
+ eq(DisplayManager.EVENT_FLAG_DISPLAY_REMOVED),
+ eq(DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS));
DisplayListener listener = captor.getValue();
final int initialRefreshRate = 60;
@@ -3075,8 +3075,8 @@
ArgumentCaptor<DisplayListener> captor =
ArgumentCaptor.forClass(DisplayListener.class);
verify(mInjector).registerDisplayListener(captor.capture(), any(Handler.class),
- eq(DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS
- | DisplayManager.EVENT_FLAG_DISPLAY_REMOVED));
+ eq(DisplayManager.EVENT_FLAG_DISPLAY_REMOVED),
+ eq(DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS));
DisplayListener listener = captor.getValue();
// Specify Limitation for different display
@@ -3115,8 +3115,8 @@
ArgumentCaptor<DisplayListener> captor =
ArgumentCaptor.forClass(DisplayListener.class);
verify(mInjector).registerDisplayListener(captor.capture(), any(Handler.class),
- eq(DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS
- | DisplayManager.EVENT_FLAG_DISPLAY_REMOVED));
+ eq(DisplayManager.EVENT_FLAG_DISPLAY_REMOVED),
+ eq(DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS));
DisplayListener listener = captor.getValue();
// Specify Limitation
@@ -3200,8 +3200,8 @@
ArgumentCaptor<DisplayListener> captor = ArgumentCaptor.forClass(DisplayListener.class);
verify(mInjector).registerDisplayListener(captor.capture(), any(Handler.class),
- eq(DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS
- | DisplayManager.EVENT_FLAG_DISPLAY_REMOVED));
+ eq(DisplayManager.EVENT_FLAG_DISPLAY_REMOVED),
+ eq(DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS));
DisplayListener listener = captor.getValue();
// Specify Sunlight limitations
@@ -3239,8 +3239,8 @@
ArgumentCaptor<DisplayListener> captor =
ArgumentCaptor.forClass(DisplayListener.class);
verify(mInjector).registerDisplayListener(captor.capture(), any(Handler.class),
- eq(DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS
- | DisplayManager.EVENT_FLAG_DISPLAY_REMOVED));
+ eq(DisplayManager.EVENT_FLAG_DISPLAY_REMOVED),
+ eq(DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS));
DisplayListener listener = captor.getValue();
// Specify Limitation for different display
@@ -3897,7 +3897,12 @@
public void registerDisplayListener(DisplayListener listener, Handler handler) {}
@Override
- public void registerDisplayListener(DisplayListener listener, Handler handler, long flag) {}
+ public void registerDisplayListener(DisplayListener listener, Handler handler,
+ long flags) {}
+
+ @Override
+ public void registerDisplayListener(DisplayListener listener, Handler handler, long flag,
+ long privateFlag) {}
@Override
public Display getDisplay(int displayId) {
diff --git a/services/tests/mockingservicestests/src/com/android/server/BatteryServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/BatteryServiceTest.java
new file mode 100644
index 0000000..5e2f80b
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/BatteryServiceTest.java
@@ -0,0 +1,338 @@
+/*
+ * Copyright (C) 2024 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.server;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.when;
+
+import android.app.ActivityManager;
+import android.app.ActivityManagerInternal;
+import android.app.AppOpsManager;
+import android.content.Context;
+import android.hardware.health.HealthInfo;
+import android.os.HandlerThread;
+import android.os.SystemClock;
+import android.os.SystemProperties;
+import android.os.UserHandle;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.SetFlagsRule;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.dx.mockito.inline.extended.ExtendedMockito;
+import com.android.internal.R;
+import com.android.internal.app.IBatteryStats;
+import com.android.modules.utils.testing.ExtendedMockitoRule;
+import com.android.server.am.BatteryStatsService;
+import com.android.server.flags.Flags;
+import com.android.server.lights.LightsManager;
+import com.android.server.lights.LogicalLight;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+@RunWith(AndroidJUnit4.class)
+public class BatteryServiceTest {
+
+ private static final int CURRENT_BATTERY_VOLTAGE = 3000;
+ private static final int VOLTAGE_LESS_THEN_ONE_PERCENT = 3029;
+ private static final int VOLTAGE_MORE_THEN_ONE_PERCENT = 3030;
+ private static final int CURRENT_BATTERY_TEMP = 300;
+ private static final int TEMP_LESS_THEN_ONE_DEGREE_CELSIUS = 305;
+ private static final int TEMP_MORE_THEN_ONE_DEGREE_CELSIUS = 310;
+ private static final int CURRENT_BATTERY_HEALTH = 2;
+ private static final int UPDATED_BATTERY_HEALTH = 3;
+ private static final int CURRENT_CHARGE_COUNTER = 4680000;
+ private static final int UPDATED_CHARGE_COUNTER = 4218000;
+ private static final int HANDLER_IDLE_TIME_MS = 5000;
+ @Rule
+ public final ExtendedMockitoRule mExtendedMockitoRule = new ExtendedMockitoRule.Builder(this)
+ .mockStatic(SystemProperties.class)
+ .mockStatic(ActivityManager.class)
+ .mockStatic(BatteryStatsService.class)
+ .build();
+ @Rule
+ public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+ @Mock
+ private Context mContextMock;
+ @Mock
+ private LightsManager mLightsManagerMock;
+ @Mock
+ private ActivityManagerInternal mActivityManagerInternalMock;
+ @Mock
+ private IBatteryStats mIBatteryStatsMock;
+
+ private BatteryService mBatteryService;
+ private String mSystemUiPackage;
+
+ /**
+ * Creates a mock and registers it to {@link LocalServices}.
+ */
+ private static <T> void addLocalServiceMock(Class<T> clazz, T mock) {
+ LocalServices.removeServiceForTest(clazz);
+ LocalServices.addService(clazz, mock);
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+
+ mSystemUiPackage = InstrumentationRegistry.getInstrumentation().getTargetContext()
+ .getResources().getString(R.string.config_systemUi);
+
+ when(mLightsManagerMock.getLight(anyInt())).thenReturn(mock(LogicalLight.class));
+ when(mActivityManagerInternalMock.isSystemReady()).thenReturn(true);
+ when(mContextMock.getResources()).thenReturn(
+ InstrumentationRegistry.getInstrumentation().getTargetContext().getResources());
+ ExtendedMockito.when(BatteryStatsService.getService()).thenReturn(mIBatteryStatsMock);
+
+ doNothing().when(mIBatteryStatsMock).setBatteryState(anyInt(), anyInt(), anyInt(), anyInt(),
+ anyInt(), anyInt(), anyInt(), anyInt(), anyLong());
+ doNothing().when(() -> SystemProperties.set(anyString(), anyString()));
+ doNothing().when(() -> ActivityManager.broadcastStickyIntent(any(),
+ eq(new String[]{mSystemUiPackage}), eq(AppOpsManager.OP_NONE),
+ eq(BatteryService.BATTERY_CHANGED_OPTIONS), eq(UserHandle.USER_ALL)));
+
+ addLocalServiceMock(LightsManager.class, mLightsManagerMock);
+ addLocalServiceMock(ActivityManagerInternal.class, mActivityManagerInternalMock);
+
+ createBatteryService();
+ }
+
+ @Test
+ public void createBatteryService_withNullLooper_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> new BatteryService(mContextMock));
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_RATE_LIMIT_BATTERY_CHANGED_BROADCAST)
+ public void onlyVoltageUpdated_lessThenOnePercent_broadcastNotSent() {
+ mBatteryService.update(createHealthInfo(VOLTAGE_LESS_THEN_ONE_PERCENT, CURRENT_BATTERY_TEMP,
+ CURRENT_CHARGE_COUNTER, CURRENT_BATTERY_HEALTH));
+
+ waitForHandlerToExecute();
+
+ verifyNumberOfTimesBroadcastSent(0);
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_RATE_LIMIT_BATTERY_CHANGED_BROADCAST)
+ public void onlyVoltageUpdated_beforeTwentySeconds_broadcastNotSent() {
+ mBatteryService.update(
+ createHealthInfo(VOLTAGE_MORE_THEN_ONE_PERCENT, CURRENT_BATTERY_TEMP,
+ CURRENT_CHARGE_COUNTER,
+ CURRENT_BATTERY_HEALTH));
+
+ waitForHandlerToExecute();
+
+ verifyNumberOfTimesBroadcastSent(0);
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_RATE_LIMIT_BATTERY_CHANGED_BROADCAST)
+ public void onlyVoltageUpdated_broadcastSent() {
+ mBatteryService.mLastBroadcastVoltageUpdateTime = SystemClock.elapsedRealtime() - 20000;
+ mBatteryService.update(createHealthInfo(VOLTAGE_MORE_THEN_ONE_PERCENT, CURRENT_BATTERY_TEMP,
+ CURRENT_CHARGE_COUNTER, CURRENT_BATTERY_HEALTH));
+
+ waitForHandlerToExecute();
+
+ verifyNumberOfTimesBroadcastSent(1);
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_RATE_LIMIT_BATTERY_CHANGED_BROADCAST)
+ public void onlyTempUpdated_lessThenOneDegreeCelsius_broadcastNotSent() {
+ mBatteryService.update(
+ createHealthInfo(CURRENT_BATTERY_VOLTAGE, TEMP_LESS_THEN_ONE_DEGREE_CELSIUS,
+ CURRENT_CHARGE_COUNTER, CURRENT_BATTERY_HEALTH));
+
+ waitForHandlerToExecute();
+
+ verifyNumberOfTimesBroadcastSent(0);
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_RATE_LIMIT_BATTERY_CHANGED_BROADCAST)
+ public void tempUpdated_broadcastSent() {
+ long lastVoltageUpdateTime = mBatteryService.mLastBroadcastVoltageUpdateTime;
+ mBatteryService.update(
+ createHealthInfo(VOLTAGE_LESS_THEN_ONE_PERCENT, TEMP_MORE_THEN_ONE_DEGREE_CELSIUS,
+ UPDATED_CHARGE_COUNTER, CURRENT_BATTERY_HEALTH));
+
+ waitForHandlerToExecute();
+
+ assertTrue(lastVoltageUpdateTime < mBatteryService.mLastBroadcastVoltageUpdateTime);
+ verifyNumberOfTimesBroadcastSent(1);
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_RATE_LIMIT_BATTERY_CHANGED_BROADCAST)
+ public void batteryHealthUpdated_voltageAndTempConst_broadcastSent() {
+ mBatteryService.update(
+ createHealthInfo(CURRENT_BATTERY_VOLTAGE, CURRENT_BATTERY_TEMP,
+ CURRENT_CHARGE_COUNTER,
+ UPDATED_BATTERY_HEALTH));
+
+ waitForHandlerToExecute();
+
+ verifyNumberOfTimesBroadcastSent(1);
+
+ // updating counter just after the health update does not triggers broadcast.
+ mBatteryService.update(
+ createHealthInfo(CURRENT_BATTERY_VOLTAGE, CURRENT_BATTERY_TEMP,
+ UPDATED_CHARGE_COUNTER,
+ UPDATED_BATTERY_HEALTH));
+
+ waitForHandlerToExecute();
+
+ verifyNumberOfTimesBroadcastSent(1);
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_RATE_LIMIT_BATTERY_CHANGED_BROADCAST)
+ public void voltageUpdated_lessThanOnePercent_flagDisabled_broadcastSent() {
+ mBatteryService.update(createHealthInfo(VOLTAGE_LESS_THEN_ONE_PERCENT, CURRENT_BATTERY_TEMP,
+ CURRENT_CHARGE_COUNTER, CURRENT_BATTERY_HEALTH));
+
+ waitForHandlerToExecute();
+
+ verifyNumberOfTimesBroadcastSent(1);
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_RATE_LIMIT_BATTERY_CHANGED_BROADCAST)
+ public void onlyChargeCounterUpdated_broadcastNotSent() {
+ mBatteryService.update(
+ createHealthInfo(CURRENT_BATTERY_VOLTAGE, CURRENT_BATTERY_TEMP,
+ UPDATED_CHARGE_COUNTER,
+ CURRENT_BATTERY_HEALTH));
+
+ waitForHandlerToExecute();
+
+ verifyNumberOfTimesBroadcastSent(0);
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_RATE_LIMIT_BATTERY_CHANGED_BROADCAST)
+ public void chargeCounterUpdated_tempUpdatedLessThanOneDegree_broadcastNotSent() {
+ mBatteryService.update(
+ createHealthInfo(CURRENT_BATTERY_VOLTAGE, TEMP_LESS_THEN_ONE_DEGREE_CELSIUS,
+ UPDATED_CHARGE_COUNTER,
+ CURRENT_BATTERY_HEALTH));
+
+ waitForHandlerToExecute();
+
+ verifyNumberOfTimesBroadcastSent(0);
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_RATE_LIMIT_BATTERY_CHANGED_BROADCAST)
+ public void onlyChargeCounterUpdated_broadcastSent() {
+ mBatteryService.update(
+ createHealthInfo(CURRENT_BATTERY_VOLTAGE, CURRENT_BATTERY_TEMP,
+ UPDATED_CHARGE_COUNTER,
+ CURRENT_BATTERY_HEALTH));
+
+ waitForHandlerToExecute();
+
+ verifyNumberOfTimesBroadcastSent(1);
+ }
+
+ private HealthInfo createHealthInfo(
+ int batteryVoltage,
+ int batteryTemperature,
+ int batteryChargeCounter,
+ int batteryHealth) {
+ HealthInfo h = new HealthInfo();
+ h.batteryVoltageMillivolts = batteryVoltage;
+ h.batteryTemperatureTenthsCelsius = batteryTemperature;
+ h.batteryChargeCounterUah = batteryChargeCounter;
+ h.batteryStatus = 5;
+ h.batteryHealth = batteryHealth;
+ h.batteryPresent = true;
+ h.batteryLevel = 100;
+ h.maxChargingCurrentMicroamps = 298125;
+ h.batteryCurrentAverageMicroamps = -2812;
+ h.batteryCurrentMicroamps = 298125;
+ h.maxChargingVoltageMicrovolts = 3000;
+ h.batteryCycleCount = 50;
+ h.chargingState = 4;
+ h.batteryCapacityLevel = 100;
+ return h;
+ }
+
+ // Creates a new battery service objects and sets the initial values.
+ private void createBatteryService() throws InterruptedException {
+ final HandlerThread handlerThread = new HandlerThread("BatteryServiceTest");
+ handlerThread.start();
+
+ mBatteryService = new BatteryService(mContextMock, handlerThread.getLooper());
+
+ // trigger the update to set the initial values.
+ mBatteryService.update(
+ createHealthInfo(CURRENT_BATTERY_VOLTAGE, CURRENT_BATTERY_TEMP,
+ CURRENT_CHARGE_COUNTER,
+ CURRENT_BATTERY_HEALTH));
+
+ waitForHandlerToExecute();
+ }
+
+ private void waitForHandlerToExecute() {
+ final CountDownLatch latch = new CountDownLatch(1);
+ mBatteryService.getHandlerForTest().post(latch::countDown);
+ boolean isExecutionComplete = false;
+
+ try {
+ isExecutionComplete = latch.await(HANDLER_IDLE_TIME_MS, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException e) {
+ fail("Handler interrupted before executing the message " + e);
+ }
+
+ assertTrue("Timed out while waiting for Handler to execute.", isExecutionComplete);
+ }
+
+ private void verifyNumberOfTimesBroadcastSent(int numberOfTimes) {
+ // Increase the numberOfTimes by 1 as one broadcast was sent initially during the test
+ // setUp.
+ verify(() -> ActivityManager.broadcastStickyIntent(any(),
+ eq(new String[]{mSystemUiPackage}), eq(AppOpsManager.OP_NONE),
+ eq(BatteryService.BATTERY_CHANGED_OPTIONS), eq(UserHandle.USER_ALL)),
+ times(++numberOfTimes));
+ }
+}
diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java
index 49665f7..613b926 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java
@@ -360,12 +360,10 @@
private void verifyGetSafeModeTimeoutMs(
boolean isInTestMode,
- boolean isConfigTimeoutSupported,
PersistableBundleWrapper carrierConfig,
long expectedTimeoutMs)
throws Exception {
doReturn(isInTestMode).when(mVcnContext).isInTestMode();
- doReturn(isConfigTimeoutSupported).when(mVcnContext).isFlagSafeModeTimeoutConfigEnabled();
final TelephonySubscriptionSnapshot snapshot = mock(TelephonySubscriptionSnapshot.class);
doReturn(carrierConfig).when(snapshot).getCarrierConfigForSubGrp(TEST_SUB_GRP);
@@ -377,16 +375,7 @@
}
@Test
- public void testGetSafeModeTimeoutMs_configTimeoutUnsupported() throws Exception {
- verifyGetSafeModeTimeoutMs(
- false /* isInTestMode */,
- false /* isConfigTimeoutSupported */,
- null /* carrierConfig */,
- TimeUnit.SECONDS.toMillis(SAFEMODE_TIMEOUT_SECONDS));
- }
-
- @Test
- public void testGetSafeModeTimeoutMs_configTimeoutSupported() throws Exception {
+ public void testGetSafeModeTimeoutMs() throws Exception {
final int carrierConfigTimeoutSeconds = 20;
final PersistableBundleWrapper carrierConfig = mock(PersistableBundleWrapper.class);
doReturn(carrierConfigTimeoutSeconds)
@@ -395,17 +384,14 @@
verifyGetSafeModeTimeoutMs(
false /* isInTestMode */,
- true /* isConfigTimeoutSupported */,
carrierConfig,
TimeUnit.SECONDS.toMillis(carrierConfigTimeoutSeconds));
}
@Test
- public void testGetSafeModeTimeoutMs_configTimeoutSupported_carrierConfigNull()
- throws Exception {
+ public void testGetSafeModeTimeoutMs_carrierConfigNull() throws Exception {
verifyGetSafeModeTimeoutMs(
false /* isInTestMode */,
- true /* isConfigTimeoutSupported */,
null /* carrierConfig */,
TimeUnit.SECONDS.toMillis(SAFEMODE_TIMEOUT_SECONDS));
}
@@ -420,7 +406,6 @@
verifyGetSafeModeTimeoutMs(
true /* isInTestMode */,
- true /* isConfigTimeoutSupported */,
carrierConfig,
TimeUnit.SECONDS.toMillis(carrierConfigTimeoutSeconds));
}
diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java
index 4c7b25a..8374fd9 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java
@@ -222,7 +222,6 @@
doReturn(mTestLooper.getLooper()).when(mVcnContext).getLooper();
doReturn(mVcnNetworkProvider).when(mVcnContext).getVcnNetworkProvider();
doReturn(mFeatureFlags).when(mVcnContext).getFeatureFlags();
- doReturn(true).when(mVcnContext).isFlagSafeModeTimeoutConfigEnabled();
doReturn(mUnderlyingNetworkController)
.when(mDeps)