From 57dd86fc988fee77b7a27f591126971a5f657c73 Mon Sep 17 00:00:00 2001 From: Julian Winkler Date: Sat, 11 Jan 2025 18:01:43 +0100 Subject: [PATCH] api-impl: misc stubs for WhatsApp --- src/api-impl/android/animation/Animator.java | 4 + .../android/animation/LayoutTransition.java | 4 + .../android/animation/ObjectAnimator.java | 4 + .../android/animation/ValueAnimator.java | 2 + src/api-impl/android/app/Activity.java | 8 + src/api-impl/android/app/ActivityManager.java | 2 + src/api-impl/android/app/Dialog.java | 5 + .../android/content/pm/SigningInfo.java | 8 + .../android/database/CursorWindow.java | 7 +- .../android/database/MatrixCursor.java | 332 ++++++++++++++++++ src/api-impl/android/graphics/Bitmap.java | 4 + src/api-impl/android/graphics/Canvas.java | 8 +- src/api-impl/android/graphics/Path.java | 10 + src/api-impl/android/text/TextUtils.java | 8 + .../android/transition/Transition.java | 14 + src/api-impl/android/view/View.java | 7 + src/api-impl/android/view/ViewGroup.java | 2 + src/api-impl/android/view/Window.java | 19 + .../android/view/animation/Animation.java | 2 + src/api-impl/android/widget/EditText.java | 2 + .../android/widget/ListPopupWindow.java | 10 + src/api-impl/android/widget/PopupWindow.java | 2 + src/api-impl/android/widget/ProgressBar.java | 4 + src/api-impl/android/widget/TextView.java | 2 + src/api-impl/meson.build | 2 + 25 files changed, 470 insertions(+), 2 deletions(-) create mode 100644 src/api-impl/android/database/MatrixCursor.java create mode 100644 src/api-impl/android/transition/Transition.java create mode 100644 src/api-impl/android/widget/ListPopupWindow.java diff --git a/src/api-impl/android/animation/Animator.java b/src/api-impl/android/animation/Animator.java index fb2ed3c8..4add8628 100644 --- a/src/api-impl/android/animation/Animator.java +++ b/src/api-impl/android/animation/Animator.java @@ -48,4 +48,8 @@ public class Animator { public void end() {} + public TimeInterpolator getInterpolator() { return null; } + + public boolean isRunning() { return false; } + } diff --git a/src/api-impl/android/animation/LayoutTransition.java b/src/api-impl/android/animation/LayoutTransition.java index ccd27709..276ef5c8 100644 --- a/src/api-impl/android/animation/LayoutTransition.java +++ b/src/api-impl/android/animation/LayoutTransition.java @@ -5,4 +5,8 @@ public class LayoutTransition { public void enableTransitionType(int transitionType) {} public void setStartDelay(int transitionType, long startDelay) {} + + public void setAnimator(int transitionType, Animator animator) {} + + public void setDuration(long duration) {} } diff --git a/src/api-impl/android/animation/ObjectAnimator.java b/src/api-impl/android/animation/ObjectAnimator.java index 0c0f709d..bb13032f 100644 --- a/src/api-impl/android/animation/ObjectAnimator.java +++ b/src/api-impl/android/animation/ObjectAnimator.java @@ -39,4 +39,8 @@ public class ObjectAnimator extends ValueAnimator { public void setPropertyName(String propertyName) {} + public static ObjectAnimator ofPropertyValuesHolder(Object target, PropertyValuesHolder... values) { + return new ObjectAnimator(); + } + } diff --git a/src/api-impl/android/animation/ValueAnimator.java b/src/api-impl/android/animation/ValueAnimator.java index 83e92fd2..0832a08c 100644 --- a/src/api-impl/android/animation/ValueAnimator.java +++ b/src/api-impl/android/animation/ValueAnimator.java @@ -73,6 +73,8 @@ public class ValueAnimator extends Animator { return 1.0f; } + public void setObjectValues(Object[] values) {} + /** * Implementors of this interface can add themselves as update listeners * to an ValueAnimator instance to receive callbacks on every animation diff --git a/src/api-impl/android/app/Activity.java b/src/api-impl/android/app/Activity.java index 861371f9..8e9bf611 100644 --- a/src/api-impl/android/app/Activity.java +++ b/src/api-impl/android/app/Activity.java @@ -587,4 +587,12 @@ public class Activity extends ContextThemeWrapper implements Window.Callback, La public View onCreateView(View parent, String name, Context context, AttributeSet attrs) { return null; } + + public boolean onSearchRequested() { + return false; + } + + public View getCurrentFocus() { + return null; + } } diff --git a/src/api-impl/android/app/ActivityManager.java b/src/api-impl/android/app/ActivityManager.java index cb676c03..d9c97cef 100644 --- a/src/api-impl/android/app/ActivityManager.java +++ b/src/api-impl/android/app/ActivityManager.java @@ -84,4 +84,6 @@ public class ActivityManager { public List getHistoricalProcessExitReasons(String pkgname, int pid, int maxNum) { return Collections.emptyList(); } + + public static boolean isUserAMonkey() {return false;} } diff --git a/src/api-impl/android/app/Dialog.java b/src/api-impl/android/app/Dialog.java index 6662e583..00cd148f 100644 --- a/src/api-impl/android/app/Dialog.java +++ b/src/api-impl/android/app/Dialog.java @@ -8,6 +8,7 @@ import android.os.Looper; import android.os.Message; import android.view.Menu; import android.view.MenuItem; +import android.view.MotionEvent; import android.view.View; import android.view.Window; @@ -174,4 +175,8 @@ public class Dialog implements Window.Callback, DialogInterface { } public void setCancelMessage(Message msg) {} + + public boolean onTouchEvent(MotionEvent event) { + return false; + } } diff --git a/src/api-impl/android/content/pm/SigningInfo.java b/src/api-impl/android/content/pm/SigningInfo.java index 1957e4b2..5812eeaa 100644 --- a/src/api-impl/android/content/pm/SigningInfo.java +++ b/src/api-impl/android/content/pm/SigningInfo.java @@ -4,4 +4,12 @@ public final class SigningInfo { public Signature[] getApkContentsSigners() { return null; } + + public boolean hasMultipleSigners() { + return false; + } + + public Signature[] getSigningCertificateHistory() { + return null; + } } diff --git a/src/api-impl/android/database/CursorWindow.java b/src/api-impl/android/database/CursorWindow.java index d27d9eec..734d79e7 100644 --- a/src/api-impl/android/database/CursorWindow.java +++ b/src/api-impl/android/database/CursorWindow.java @@ -337,7 +337,12 @@ public class CursorWindow extends SQLiteClosable implements Parcelable { * @return The value of the field as a string. */ public String getString(int row, int column) { - return String.valueOf(rows.get(row - startPos)[column]); + Object value = rows.get(row - startPos)[column]; + if (value == null) { + return null; + } else { + return String.valueOf(value); + } } /** diff --git a/src/api-impl/android/database/MatrixCursor.java b/src/api-impl/android/database/MatrixCursor.java new file mode 100644 index 00000000..0147b104 --- /dev/null +++ b/src/api-impl/android/database/MatrixCursor.java @@ -0,0 +1,332 @@ +/* + * Copyright (C) 2007 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 android.database; +import java.util.ArrayList; + +/** + * A mutable cursor implementation backed by an array of {@code Object}s. Use + * {@link #newRow()} to add rows. Automatically expands internal capacity + * as needed. + */ +public class MatrixCursor extends AbstractCursor { + + private final String[] columnNames; + private Object[] data; + private int rowCount = 0; + private final int columnCount; + + /** + * Constructs a new cursor with the given initial capacity. + * + * @param columnNames names of the columns, the ordering of which + * determines column ordering elsewhere in this cursor + * @param initialCapacity in rows + */ + public MatrixCursor(String[] columnNames, int initialCapacity) { + this.columnNames = columnNames; + this.columnCount = columnNames.length; + + if (initialCapacity < 1) { + initialCapacity = 1; + } + + this.data = new Object[columnCount * initialCapacity]; + } + + /** + * Constructs a new cursor. + * + * @param columnNames names of the columns, the ordering of which + * determines column ordering elsewhere in this cursor + */ + public MatrixCursor(String[] columnNames) { + this(columnNames, 16); + } + + /** + * Gets value at the given column for the current row. + */ + private Object get(int column) { + if (column < 0 || column >= columnCount) { + throw new IndexOutOfBoundsException("Requested column: " + column + ", # of columns: " + columnCount); + } + if (mPos < 0) { + throw new IndexOutOfBoundsException("Before first row."); + } + if (mPos >= rowCount) { + throw new IndexOutOfBoundsException("After last row."); + } + return data[mPos * columnCount + column]; + } + + /** + * Adds a new row to the end and returns a builder for that row. Not safe + * for concurrent use. + * + * @return builder which can be used to set the column values for the new + * row + */ + public RowBuilder newRow() { + final int row = rowCount++; + final int endIndex = rowCount * columnCount; + ensureCapacity(endIndex); + return new RowBuilder(row); + } + + /** + * Adds a new row to the end with the given column values. Not safe + * for concurrent use. + * + * @throws IllegalArgumentException if {@code columnValues.length != + * columnNames.length} + * @param columnValues in the same order as the the column names specified + * at cursor construction time + */ + public void addRow(Object[] columnValues) { + if (columnValues.length != columnCount) { + throw new IllegalArgumentException("columnNames.length = " + columnCount + ", columnValues.length = " + columnValues.length); + } + + int start = rowCount++ * columnCount; + ensureCapacity(start + columnCount); + System.arraycopy(columnValues, 0, data, start, columnCount); + } + + /** + * Adds a new row to the end with the given column values. Not safe + * for concurrent use. + * + * @throws IllegalArgumentException if {@code columnValues.size() != + * columnNames.length} + * @param columnValues in the same order as the the column names specified + * at cursor construction time + */ + public void addRow(Iterable columnValues) { + int start = rowCount * columnCount; + int end = start + columnCount; + ensureCapacity(end); + + if (columnValues instanceof ArrayList) { + addRow((ArrayList)columnValues, start); + return; + } + + int current = start; + Object[] localData = data; + for (Object columnValue : columnValues) { + if (current == end) { + // TODO: null out row? + throw new IllegalArgumentException( + "columnValues.size() > columnNames.length"); + } + localData[current++] = columnValue; + } + + if (current != end) { + // TODO: null out row? + throw new IllegalArgumentException( + "columnValues.size() < columnNames.length"); + } + + // Increase row count here in case we encounter an exception. + rowCount++; + } + + /** + * Optimization for {@link ArrayList}. + */ + private void addRow(ArrayList columnValues, int start) { + int size = columnValues.size(); + if (size != columnCount) { + throw new IllegalArgumentException("columnNames.length = " + columnCount + ", columnValues.size() = " + size); + } + + rowCount++; + Object[] localData = data; + for (int i = 0; i < size; i++) { + localData[start + i] = columnValues.get(i); + } + } + + /** + * Ensures that this cursor has enough capacity. + */ + private void ensureCapacity(int size) { + if (size > data.length) { + Object[] oldData = this.data; + int newSize = data.length * 2; + if (newSize < size) { + newSize = size; + } + this.data = new Object[newSize]; + System.arraycopy(oldData, 0, this.data, 0, oldData.length); + } + } + + /** + * Builds a row of values using either of these approaches: + * + * Undefined values are left as {@code null}. + */ + public class RowBuilder { + private final int row; + private final int endIndex; + + private int index; + + RowBuilder(int row) { + this.row = row; + this.index = row * columnCount; + this.endIndex = index + columnCount; + } + + /** + * Sets the next column value in this row. + * + * @throws CursorIndexOutOfBoundsException if you try to add too many + * values + * @return this builder to support chaining + */ + public RowBuilder add(Object columnValue) { + if (index == endIndex) { + throw new IndexOutOfBoundsException( + "No more columns left."); + } + + data[index++] = columnValue; + return this; + } + + /** + * Offer value for possible inclusion if this cursor defines the given + * column. Columns not defined by the cursor are silently ignored. + * + * @return this builder to support chaining + */ + public RowBuilder add(String columnName, Object value) { + for (int i = 0; i < columnNames.length; i++) { + if (columnName.equals(columnNames[i])) { + data[(row * columnCount) + i] = value; + } + } + return this; + } + + /** + * @hide + */ + public final RowBuilder add(int columnIndex, Object value) { + data[(row * columnCount) + columnIndex] = value; + return this; + } + } + + // AbstractCursor implementation. + + @Override + public int getCount() { + return rowCount; + } + + @Override + public String[] getColumnNames() { + return columnNames; + } + + @Override + public String getString(int column) { + Object value = get(column); + if (value == null) + return null; + return value.toString(); + } + + @Override + public short getShort(int column) { + Object value = get(column); + if (value == null) + return 0; + if (value instanceof Number) + return ((Number)value).shortValue(); + return Short.parseShort(value.toString()); + } + + @Override + public int getInt(int column) { + Object value = get(column); + if (value == null) + return 0; + if (value instanceof Number) + return ((Number)value).intValue(); + return Integer.parseInt(value.toString()); + } + + @Override + public long getLong(int column) { + Object value = get(column); + if (value == null) + return 0; + if (value instanceof Number) + return ((Number)value).longValue(); + return Long.parseLong(value.toString()); + } + + @Override + public float getFloat(int column) { + Object value = get(column); + if (value == null) + return 0.0f; + if (value instanceof Number) + return ((Number)value).floatValue(); + return Float.parseFloat(value.toString()); + } + + @Override + public double getDouble(int column) { + Object value = get(column); + if (value == null) + return 0.0d; + if (value instanceof Number) + return ((Number)value).doubleValue(); + return Double.parseDouble(value.toString()); + } + + @Override + public byte[] getBlob(int column) { + Object value = get(column); + return (byte[])value; + } + + @Override + public int getType(int column) { + return DatabaseUtils.getTypeOfObject(get(column)); + } + + @Override + public boolean isNull(int column) { + return get(column) == null; + } +} diff --git a/src/api-impl/android/graphics/Bitmap.java b/src/api-impl/android/graphics/Bitmap.java index 15e54177..e8fd6c50 100644 --- a/src/api-impl/android/graphics/Bitmap.java +++ b/src/api-impl/android/graphics/Bitmap.java @@ -180,6 +180,10 @@ public final class Bitmap { buffer.position(buffer.position() + getAllocationByteCount()); } + public int getByteCount() { + return getAllocationByteCount(); + } + @SuppressWarnings("deprecation") @Override protected void finalize() throws Throwable { diff --git a/src/api-impl/android/graphics/Canvas.java b/src/api-impl/android/graphics/Canvas.java index e2f2d5df..fe5d37cb 100644 --- a/src/api-impl/android/graphics/Canvas.java +++ b/src/api-impl/android/graphics/Canvas.java @@ -6,7 +6,11 @@ public class Canvas { private Bitmap bitmap; private GskCanvas gsk_canvas; - public Canvas() {} + public Canvas() { + if (!(this instanceof GskCanvas)) { + gsk_canvas = new GskCanvas(0); + } + } public Canvas(Bitmap bmp) { this.bitmap = bmp; @@ -462,4 +466,6 @@ public class Canvas { outRect.set(0, 0, 100, 100); return true; } + + public void drawPaint(Paint paint) {} } diff --git a/src/api-impl/android/graphics/Path.java b/src/api-impl/android/graphics/Path.java index dd1b80ad..0646c618 100644 --- a/src/api-impl/android/graphics/Path.java +++ b/src/api-impl/android/graphics/Path.java @@ -92,6 +92,10 @@ public class Path { public void arcTo(RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo) {} + public void arcTo(RectF oval, float startAngle, float sweepAngle) {} + + public void arcTo(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean forceMoveTo) {} + public void rMoveTo(float x, float y) { native_rel_move_to(getBuilder(), x, y); } @@ -118,6 +122,10 @@ public class Path { addPath(path, matrix); } + public void addPath(Path path) { + addPath(path, Matrix.IDENTITY_MATRIX); + } + public void addRect(RectF rect, Direction direction) { native_add_rect(getBuilder(), rect.left, rect.top, rect.right, rect.bottom); } @@ -138,6 +146,8 @@ public class Path { public void addOval(RectF rect, Direction direction) {} + public void addCircle(float x, float y, float radius, Direction direction) {} + public void transform(Matrix matrix) { builder = native_transform(getGskPath(), matrix.ni()); path = 0; diff --git a/src/api-impl/android/text/TextUtils.java b/src/api-impl/android/text/TextUtils.java index b06ddebe..437fef43 100644 --- a/src/api-impl/android/text/TextUtils.java +++ b/src/api-impl/android/text/TextUtils.java @@ -338,4 +338,12 @@ public class TextUtils { public static String htmlEncode(String s) { return s; } + + public static CharSequence concat(CharSequence[] array) { + StringBuilder sb = new StringBuilder(); + for (CharSequence cs : array) { + sb.append(cs); + } + return sb; + } } diff --git a/src/api-impl/android/transition/Transition.java b/src/api-impl/android/transition/Transition.java new file mode 100644 index 00000000..ace46d18 --- /dev/null +++ b/src/api-impl/android/transition/Transition.java @@ -0,0 +1,14 @@ +package android.transition; + +public class Transition { + + public interface TransitionListener {} + + public Transition clone() { + return new Transition(); + } + + public Transition addListener(TransitionListener listener) { + return this; + } +} diff --git a/src/api-impl/android/view/View.java b/src/api-impl/android/view/View.java index 2301bbe6..be427d7d 100644 --- a/src/api-impl/android/view/View.java +++ b/src/api-impl/android/view/View.java @@ -15,6 +15,7 @@ import android.graphics.Rect; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.os.Binder; +import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Looper; @@ -2112,4 +2113,10 @@ public class View implements Drawable.Callback { public float getTransitionAlpha() { return 1.0f; } + + public void onWindowFocusChanged(boolean hasFocus) {} + + public void setAnimation(Animation animation) {} + + public boolean performAccessibilityAction(int action, Bundle arguments) { return false; } } diff --git a/src/api-impl/android/view/ViewGroup.java b/src/api-impl/android/view/ViewGroup.java index ac7eff68..99e32ecd 100644 --- a/src/api-impl/android/view/ViewGroup.java +++ b/src/api-impl/android/view/ViewGroup.java @@ -422,6 +422,8 @@ public class ViewGroup extends View implements ViewParent, ViewManager { // FIXME } + public boolean getClipToPadding() { return false; } + public static class LayoutParams { public static final int FILL_PARENT = -1; public static final int MATCH_PARENT = -1; diff --git a/src/api-impl/android/view/Window.java b/src/api-impl/android/view/Window.java index be99caf0..cb3e93d7 100644 --- a/src/api-impl/android/view/Window.java +++ b/src/api-impl/android/view/Window.java @@ -2,6 +2,7 @@ package android.view; import android.content.Context; import android.graphics.drawable.Drawable; +import android.transition.Transition; import android.view.SurfaceHolder; import android.widget.FrameLayout; @@ -135,4 +136,22 @@ public class Window { public void setTitle(CharSequence title) { set_title(native_window, title != null ? title.toString() : context.getPackageName()); } + + public Transition getSharedElementEnterTransition() { + return new Transition(); + } + + public void setSharedElementExitTransition(Transition transition) {} + + public void setSharedElementReenterTransition(Transition transition) {} + + public void setSharedElementReturnTransition(Transition transition) {} + + public Transition getSharedElementExitTransition() { + return new Transition(); + } + + public Transition getSharedElementReenterTransition() { + return new Transition(); + } } diff --git a/src/api-impl/android/view/animation/Animation.java b/src/api-impl/android/view/animation/Animation.java index e5453f57..9e660968 100644 --- a/src/api-impl/android/view/animation/Animation.java +++ b/src/api-impl/android/view/animation/Animation.java @@ -34,4 +34,6 @@ public class Animation { public void setRepeatCount(int count) {} public void reset() {} + + public void start() {} } diff --git a/src/api-impl/android/widget/EditText.java b/src/api-impl/android/widget/EditText.java index 35d7c9a8..01047d2c 100644 --- a/src/api-impl/android/widget/EditText.java +++ b/src/api-impl/android/widget/EditText.java @@ -56,4 +56,6 @@ public class EditText extends TextView { @Override public void setCompoundDrawables(Drawable left, Drawable top, Drawable right, Drawable bottom) {} + + public void selectAll() {} } diff --git a/src/api-impl/android/widget/ListPopupWindow.java b/src/api-impl/android/widget/ListPopupWindow.java new file mode 100644 index 00000000..c8ee45e7 --- /dev/null +++ b/src/api-impl/android/widget/ListPopupWindow.java @@ -0,0 +1,10 @@ +package android.widget; + +import android.content.Context; + +public class ListPopupWindow { + + public ListPopupWindow(Context context) {} + + public void setAdapter(ListAdapter adapter) {} +} diff --git a/src/api-impl/android/widget/PopupWindow.java b/src/api-impl/android/widget/PopupWindow.java index c9995531..9d074848 100644 --- a/src/api-impl/android/widget/PopupWindow.java +++ b/src/api-impl/android/widget/PopupWindow.java @@ -99,4 +99,6 @@ public class PopupWindow { } public void setAnimationStyle(int animationStyle) {} + + public void setTouchModal(boolean touchModal) {} } diff --git a/src/api-impl/android/widget/ProgressBar.java b/src/api-impl/android/widget/ProgressBar.java index 42bade56..c2653e5c 100644 --- a/src/api-impl/android/widget/ProgressBar.java +++ b/src/api-impl/android/widget/ProgressBar.java @@ -89,6 +89,10 @@ public class ProgressBar extends View { native_setProgress(widget, progress / (float)max); } + public void setProgress(int progress, boolean animate) { + setProgress(progress); + } + public void setSecondaryProgress(int secondaryProgress) {} public int getProgress() { diff --git a/src/api-impl/android/widget/TextView.java b/src/api-impl/android/widget/TextView.java index 685d2ad8..42f5677c 100644 --- a/src/api-impl/android/widget/TextView.java +++ b/src/api-impl/android/widget/TextView.java @@ -366,4 +366,6 @@ public class TextView extends View { public void setAutoSizeTextTypeUniformWithPresetSizes(int[] presetSizes, int unit) {} public void setCompoundDrawableTintList(ColorStateList tint) {} + + public void setIncludeFontPadding(boolean includePadding) {} } diff --git a/src/api-impl/meson.build b/src/api-impl/meson.build index faf78abf..30877ece 100644 --- a/src/api-impl/meson.build +++ b/src/api-impl/meson.build @@ -141,6 +141,7 @@ srcs = [ 'android/database/DatabaseErrorHandler.java', 'android/database/DatabaseUtils.java', 'android/database/DefaultDatabaseErrorHandler.java', + 'android/database/MatrixCursor.java', 'android/database/Observable.java', 'android/database/SQLException.java', 'android/database/sqlite/DatabaseErrorHandler.java', @@ -414,6 +415,7 @@ srcs = [ 'android/text/style/UpdateLayout.java', 'android/text/style/URLSpan.java', 'android/text/util/Linkify.java', + 'android/transition/Transition.java', 'android/util/AndroidException.java', 'android/util/AndroidRuntimeException.java', 'android/util/ArrayMap.java',