• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.internal.widget.remotecompose.core;
17 
18 import android.annotation.NonNull;
19 import android.annotation.Nullable;
20 
21 import com.android.internal.widget.remotecompose.core.operations.FloatExpression;
22 import com.android.internal.widget.remotecompose.core.operations.ShaderData;
23 import com.android.internal.widget.remotecompose.core.operations.Theme;
24 import com.android.internal.widget.remotecompose.core.operations.Utils;
25 import com.android.internal.widget.remotecompose.core.operations.layout.Component;
26 import com.android.internal.widget.remotecompose.core.operations.utilities.ArrayAccess;
27 import com.android.internal.widget.remotecompose.core.operations.utilities.CollectionsAccess;
28 import com.android.internal.widget.remotecompose.core.operations.utilities.DataMap;
29 import com.android.internal.widget.remotecompose.core.operations.utilities.IntMap;
30 
31 import java.time.LocalDateTime;
32 import java.time.OffsetDateTime;
33 import java.time.ZoneId;
34 import java.time.ZoneOffset;
35 
36 /**
37  * Specify an abstract context used to playback RemoteCompose documents
38  *
39  * <p>This allows us to intercept the different operations in a document and react to them.
40  *
41  * <p>We also contain a PaintContext, so that any operation can draw as needed.
42  */
43 public abstract class RemoteContext {
44     private static final int MAX_OP_COUNT = 20_000; // Maximum cmds per frame
45     protected @NonNull CoreDocument mDocument =
46             new CoreDocument(); // todo: is this a valid way to initialize? bbade@
47     public @NonNull RemoteComposeState mRemoteComposeState =
48             new RemoteComposeState(); // todo, is this a valid use of RemoteComposeState -- bbade@
49     private long mDocLoadTime = System.currentTimeMillis();
50     @Nullable protected PaintContext mPaintContext = null;
51     protected float mDensity = Float.NaN;
52 
53     @NonNull ContextMode mMode = ContextMode.UNSET;
54 
55     int mDebug = 0;
56 
57     private int mOpCount;
58     private int mTheme = Theme.UNSPECIFIED;
59 
60     public float mWidth = 0f;
61     public float mHeight = 0f;
62     private float mAnimationTime;
63 
64     private boolean mAnimate = true;
65 
66     public @Nullable Component mLastComponent;
67     public long currentTime = 0L;
68 
69     private boolean mUseChoreographer = true;
70 
71     /**
72      * Returns true if the document has been encoded for at least the given version MAJOR.MINOR
73      *
74      * @param major major version number
75      * @param minor minor version number
76      * @param patch patch version number
77      * @return true if the document was written at least with the given version
78      */
supportsVersion(int major, int minor, int patch)79     public boolean supportsVersion(int major, int minor, int patch) {
80         return mDocument.mVersion.supportsVersion(major, minor, patch);
81     }
82 
getDensity()83     public float getDensity() {
84         return mDensity;
85     }
86 
87     /**
88      * Set the density of the document
89      *
90      * @param density
91      */
setDensity(float density)92     public void setDensity(float density) {
93         if (!Float.isNaN(density) && density > 0) {
94             mDensity = density;
95         }
96     }
97 
98     /**
99      * Get the time the document was loaded
100      *
101      * @return time in ms since the document was loaded
102      */
getDocLoadTime()103     public long getDocLoadTime() {
104         return mDocLoadTime;
105     }
106 
107     /** Set the time the document was loaded */
setDocLoadTime()108     public void setDocLoadTime() {
109         mDocLoadTime = System.currentTimeMillis();
110     }
111 
isAnimationEnabled()112     public boolean isAnimationEnabled() {
113         return mAnimate;
114     }
115 
setAnimationEnabled(boolean value)116     public void setAnimationEnabled(boolean value) {
117         mAnimate = value;
118     }
119 
120     /**
121      * Provide access to the table of collections
122      *
123      * @return the CollectionsAccess implementation
124      */
getCollectionsAccess()125     public @Nullable CollectionsAccess getCollectionsAccess() {
126         return mRemoteComposeState;
127     }
128 
129     /**
130      * Load a path under an id. Paths can be use in clip drawPath and drawTweenPath
131      *
132      * @param instanceId the id to save this path under
133      * @param floatPath the path as a float array
134      */
loadPathData(int instanceId, @NonNull float[] floatPath)135     public abstract void loadPathData(int instanceId, @NonNull float[] floatPath);
136 
137     /**
138      * Load a path under an id. Paths can be use in clip drawPath and drawTweenPath
139      *
140      * @param instanceId
141      * @return the a
142      */
getPathData(int instanceId)143     public abstract @Nullable float[] getPathData(int instanceId);
144 
145     /**
146      * Associate a name with a give id.
147      *
148      * @param varName the name
149      * @param varId the id (color,integer,float etc.)
150      * @param varType thetype
151      */
loadVariableName(@onNull String varName, int varId, int varType)152     public abstract void loadVariableName(@NonNull String varName, int varId, int varType);
153 
154     /**
155      * Save a color under a given id
156      *
157      * @param id the id of the color
158      * @param color the color to set
159      */
loadColor(int id, int color)160     public abstract void loadColor(int id, int color);
161 
162     /**
163      * Set the animation time allowing the creator to control animation rates
164      *
165      * @param time the animation time in seconds
166      */
setAnimationTime(float time)167     public void setAnimationTime(float time) {
168         mAnimationTime = time;
169     }
170 
171     /**
172      * gets the time animation clock as float in seconds
173      *
174      * @return a monotonic time in seconds (arbitrary zero point)
175      */
getAnimationTime()176     public float getAnimationTime() {
177         return mAnimationTime;
178     }
179 
180     /**
181      * Set the value of a named Color. This overrides the color in the document
182      *
183      * @param colorName the name of the color to override
184      * @param color Override the default color
185      */
setNamedColorOverride(@onNull String colorName, int color)186     public abstract void setNamedColorOverride(@NonNull String colorName, int color);
187 
188     /**
189      * Set the value of a named String. This overrides the string in the document
190      *
191      * @param stringName the name of the string to override
192      * @param value Override the default string
193      */
setNamedStringOverride(@onNull String stringName, @NonNull String value)194     public abstract void setNamedStringOverride(@NonNull String stringName, @NonNull String value);
195 
196     /**
197      * Allows to clear a named String.
198      *
199      * <p>If an override exists, we revert back to the default value in the document.
200      *
201      * @param stringName the name of the string to override
202      */
clearNamedStringOverride(@onNull String stringName)203     public abstract void clearNamedStringOverride(@NonNull String stringName);
204 
205     /**
206      * Set the value of a named Integer. This overrides the integer in the document
207      *
208      * @param integerName the name of the integer to override
209      * @param value Override the default integer
210      */
setNamedIntegerOverride(@onNull String integerName, int value)211     public abstract void setNamedIntegerOverride(@NonNull String integerName, int value);
212 
213     /**
214      * Allows to clear a named Integer.
215      *
216      * <p>If an override exists, we revert back to the default value in the document.
217      *
218      * @param integerName the name of the integer to override
219      */
clearNamedIntegerOverride(@onNull String integerName)220     public abstract void clearNamedIntegerOverride(@NonNull String integerName);
221 
222     /**
223      * Set the value of a named float. This overrides the float in the document
224      *
225      * @param floatName the name of the float to override
226      * @param value Override the default float
227      */
setNamedFloatOverride(String floatName, float value)228     public abstract void setNamedFloatOverride(String floatName, float value);
229 
230     /**
231      * Allows to clear a named Float.
232      *
233      * <p>If an override exists, we revert back to the default value in the document.
234      *
235      * @param floatName the name of the float to override
236      */
clearNamedFloatOverride(String floatName)237     public abstract void clearNamedFloatOverride(String floatName);
238 
239     /**
240      * Set the value of a named long. This modifies the content of a LongConstant
241      *
242      * @param name the name of the float to override
243      * @param value Override the default float
244      */
setNamedLong(String name, long value)245     public abstract void setNamedLong(String name, long value);
246 
247     /**
248      * Set the value of a named Object. This overrides the Object in the document
249      *
250      * @param dataName the name of the Object to override
251      * @param value Override the default float
252      */
setNamedDataOverride(String dataName, Object value)253     public abstract void setNamedDataOverride(String dataName, Object value);
254 
255     /**
256      * Allows to clear a named Object.
257      *
258      * <p>If an override exists, we revert back to the default value in the document.
259      *
260      * @param dataName the name of the Object to override
261      */
clearNamedDataOverride(String dataName)262     public abstract void clearNamedDataOverride(String dataName);
263 
264     /**
265      * Support Collections by registering this collection
266      *
267      * @param id id of the collection
268      * @param collection the collection under this id
269      */
addCollection(int id, @NonNull ArrayAccess collection)270     public abstract void addCollection(int id, @NonNull ArrayAccess collection);
271 
272     /**
273      * put DataMap under an id
274      *
275      * @param id the id of the DataMap
276      * @param map the DataMap
277      */
putDataMap(int id, @NonNull DataMap map)278     public abstract void putDataMap(int id, @NonNull DataMap map);
279 
280     /**
281      * Get a DataMap given an id
282      *
283      * @param id the id of the DataMap
284      * @return the DataMap
285      */
getDataMap(int id)286     public abstract @Nullable DataMap getDataMap(int id);
287 
288     /**
289      * Run an action
290      *
291      * @param id the id of the action
292      * @param metadata the metadata of the action
293      */
runAction(int id, @NonNull String metadata)294     public abstract void runAction(int id, @NonNull String metadata);
295 
296     // TODO: we might add an interface to group all valid parameter types
297 
298     /**
299      * Run an action with a named parameter
300      *
301      * @param textId the text id of the action
302      * @param value the value of the parameter
303      */
runNamedAction(int textId, Object value)304     public abstract void runNamedAction(int textId, Object value);
305 
306     /**
307      * Put an object under an id
308      *
309      * @param mId the id of the object
310      * @param command the object
311      */
putObject(int mId, @NonNull Object command)312     public abstract void putObject(int mId, @NonNull Object command);
313 
314     /**
315      * Get an object given an id
316      *
317      * @param mId the id of the object
318      * @return the object
319      */
getObject(int mId)320     public abstract @Nullable Object getObject(int mId);
321 
322     /**
323      * Add a touch listener to the context
324      *
325      * @param touchExpression the touch expression
326      */
addTouchListener(TouchListener touchExpression)327     public void addTouchListener(TouchListener touchExpression) {}
328 
329     /**
330      * Vibrate the device
331      *
332      * @param type 0 = none, 1-21 ,see HapticFeedbackConstants
333      */
hapticEffect(int type)334     public abstract void hapticEffect(int type);
335 
336     /** Set the repaint flag. This will trigger a repaint of the current document. */
needsRepaint()337     public void needsRepaint() {
338         if (mPaintContext != null) {
339             mPaintContext.needsRepaint();
340         }
341     }
342 
343     /**
344      * Returns true if we should use the choreographter
345      *
346      * @return true if we use the choreographer
347      */
useChoreographer()348     public boolean useChoreographer() {
349         return mUseChoreographer;
350     }
351 
352     /**
353      * Set to true to use the android choreographer
354      *
355      * @param value
356      */
setUseChoreographer(boolean value)357     public void setUseChoreographer(boolean value) {
358         mUseChoreographer = value;
359     }
360 
361     /**
362      * The context can be used in a few different mode, allowing operations to skip being executed:
363      * - UNSET : all operations will get executed - DATA : only operations dealing with DATA (eg
364      * loading a bitmap) should execute - PAINT : only operations painting should execute
365      */
366     public enum ContextMode {
367         UNSET,
368         DATA,
369         PAINT
370     }
371 
getTheme()372     public int getTheme() {
373         return mTheme;
374     }
375 
setTheme(int theme)376     public void setTheme(int theme) {
377         this.mTheme = theme;
378     }
379 
getMode()380     public @NonNull ContextMode getMode() {
381         return mMode;
382     }
383 
setMode(@onNull ContextMode mode)384     public void setMode(@NonNull ContextMode mode) {
385         this.mMode = mode;
386     }
387 
388     @Nullable
getPaintContext()389     public PaintContext getPaintContext() {
390         return mPaintContext;
391     }
392 
setPaintContext(@onNull PaintContext paintContext)393     public void setPaintContext(@NonNull PaintContext paintContext) {
394         this.mPaintContext = paintContext;
395     }
396 
getDocument()397     public @Nullable CoreDocument getDocument() {
398         return mDocument;
399     }
400 
isDebug()401     public boolean isDebug() {
402         return mDebug == 1;
403     }
404 
isVisualDebug()405     public boolean isVisualDebug() {
406         return mDebug == 2;
407     }
408 
setDebug(int debug)409     public void setDebug(int debug) {
410         this.mDebug = debug;
411     }
412 
setDocument(@onNull CoreDocument document)413     public void setDocument(@NonNull CoreDocument document) {
414         this.mDocument = document;
415     }
416 
417     ///////////////////////////////////////////////////////////////////////////////////////////////
418     // Operations
419     ///////////////////////////////////////////////////////////////////////////////////////////////
420 
421     /**
422      * Set the main information about a document
423      *
424      * @param majorVersion major version of the document protocol used
425      * @param minorVersion minor version of the document protocol used
426      * @param patchVersion patch version of the document protocol used
427      * @param width original width of the document when created
428      * @param height original height of the document when created
429      * @param capabilities bitmask of capabilities used in the document (TBD)
430      * @param properties properties of the document (TBD)
431      */
header( int majorVersion, int minorVersion, int patchVersion, int width, int height, long capabilities, IntMap<Object> properties)432     public void header(
433             int majorVersion,
434             int minorVersion,
435             int patchVersion,
436             int width,
437             int height,
438             long capabilities,
439             IntMap<Object> properties) {
440         mRemoteComposeState.setWindowWidth(width);
441         mRemoteComposeState.setWindowHeight(height);
442         mDocument.setVersion(majorVersion, minorVersion, patchVersion);
443         mDocument.setWidth(width);
444         mDocument.setHeight(height);
445         mDocument.setRequiredCapabilities(capabilities);
446         mDocument.setProperties(properties);
447     }
448 
449     /**
450      * Sets the way the player handles the content
451      *
452      * @param scroll set the horizontal behavior (NONE|SCROLL_HORIZONTAL|SCROLL_VERTICAL)
453      * @param alignment set the alignment of the content (TOP|CENTER|BOTTOM|START|END)
454      * @param sizing set the type of sizing for the content (NONE|SIZING_LAYOUT|SIZING_SCALE)
455      * @param mode set the mode of sizing, either LAYOUT modes or SCALE modes the LAYOUT modes are:
456      *     - LAYOUT_MATCH_PARENT - LAYOUT_WRAP_CONTENT or adding an horizontal mode and a vertical
457      *     mode: - LAYOUT_HORIZONTAL_MATCH_PARENT - LAYOUT_HORIZONTAL_WRAP_CONTENT -
458      *     LAYOUT_HORIZONTAL_FIXED - LAYOUT_VERTICAL_MATCH_PARENT - LAYOUT_VERTICAL_WRAP_CONTENT -
459      *     LAYOUT_VERTICAL_FIXED The LAYOUT_*_FIXED modes will use the intrinsic document size
460      */
setRootContentBehavior(int scroll, int alignment, int sizing, int mode)461     public void setRootContentBehavior(int scroll, int alignment, int sizing, int mode) {
462         mDocument.setRootContentBehavior(scroll, alignment, sizing, mode);
463     }
464 
465     /**
466      * Set a content description for the document
467      *
468      * @param contentDescriptionId the text id pointing at the description
469      */
setDocumentContentDescription(int contentDescriptionId)470     public void setDocumentContentDescription(int contentDescriptionId) {
471         String contentDescription = (String) mRemoteComposeState.getFromId(contentDescriptionId);
472         mDocument.setContentDescription(contentDescription);
473     }
474 
475     ///////////////////////////////////////////////////////////////////////////////////////////////
476     // Data handling
477     ///////////////////////////////////////////////////////////////////////////////////////////////
478 
479     /**
480      * Save a bitmap under an imageId
481      *
482      * @param imageId the id of the image
483      * @param encoding how the data is encoded 0 = png, 1 = raw, 2 = url
484      * @param type the type of the data 0 = RGBA 8888, 1 = 888, 2 = 8 gray
485      * @param width the width of the image
486      * @param height the height of the image
487      * @param bitmap the bytes that represent the image
488      */
loadBitmap( int imageId, short encoding, short type, int width, int height, @NonNull byte[] bitmap)489     public abstract void loadBitmap(
490             int imageId, short encoding, short type, int width, int height, @NonNull byte[] bitmap);
491 
492     /**
493      * Save a string under a given id
494      *
495      * @param id the id of the string
496      * @param text the value to set
497      */
loadText(int id, @NonNull String text)498     public abstract void loadText(int id, @NonNull String text);
499 
500     /**
501      * Get a string given an id
502      *
503      * @param id the id of the string
504      * @return
505      */
getText(int id)506     public abstract @Nullable String getText(int id);
507 
508     /**
509      * Load a float
510      *
511      * @param id id of the float
512      * @param value the value to set
513      */
loadFloat(int id, float value)514     public abstract void loadFloat(int id, float value);
515 
516     /**
517      * Override an existing float value
518      *
519      * @param id
520      * @param value
521      */
overrideFloat(int id, float value)522     public abstract void overrideFloat(int id, float value);
523 
524     /**
525      * Load a integer
526      *
527      * @param id id of the integer
528      * @param value the value to set
529      */
loadInteger(int id, int value)530     public abstract void loadInteger(int id, int value);
531 
532     /**
533      * Override an existing int value
534      *
535      * @param id
536      * @param value
537      */
overrideInteger(int id, int value)538     public abstract void overrideInteger(int id, int value);
539 
540     /**
541      * Override an existing text value
542      *
543      * @param id
544      * @param valueId
545      */
overrideText(int id, int valueId)546     public abstract void overrideText(int id, int valueId);
547 
548     /**
549      * Load an animated float associated with an id Todo: Remove? cc @hoford
550      *
551      * @param id the id of the float
552      * @param animatedFloat The animated float
553      */
loadAnimatedFloat(int id, @NonNull FloatExpression animatedFloat)554     public abstract void loadAnimatedFloat(int id, @NonNull FloatExpression animatedFloat);
555 
556     /**
557      * Save a shader under and ID
558      *
559      * @param id the id of the Shader
560      * @param value the shader
561      */
loadShader(int id, @NonNull ShaderData value)562     public abstract void loadShader(int id, @NonNull ShaderData value);
563 
564     /**
565      * Get a float given an id
566      *
567      * @param id the id of the float
568      * @return the value of the float
569      */
getFloat(int id)570     public abstract float getFloat(int id);
571 
572     /**
573      * Get a Integer given an id
574      *
575      * @param id of the integer
576      * @return the value
577      */
getInteger(int id)578     public abstract int getInteger(int id);
579 
580     /**
581      * Get a Long given an id
582      *
583      * @param id of the long
584      * @return the value
585      */
getLong(int id)586     public abstract long getLong(int id);
587 
588     /**
589      * Get the color given and ID
590      *
591      * @param id of the color
592      * @return the color
593      */
getColor(int id)594     public abstract int getColor(int id);
595 
596     /**
597      * called to notify system that a command is interested in a variable
598      *
599      * @param id track when this id changes value
600      * @param variableSupport call back when value changes
601      */
listensTo(int id, @NonNull VariableSupport variableSupport)602     public abstract void listensTo(int id, @NonNull VariableSupport variableSupport);
603 
604     /**
605      * Notify commands with variables have changed
606      *
607      * @return the number of ms to next update
608      */
updateOps()609     public abstract int updateOps();
610 
611     /**
612      * Get a shader given the id
613      *
614      * @param id get a shader given the id
615      * @return The shader
616      */
617     @Nullable
getShader(int id)618     public abstract ShaderData getShader(int id);
619 
620     public static final int ID_CONTINUOUS_SEC = 1;
621     public static final int ID_TIME_IN_SEC = 2;
622     public static final int ID_TIME_IN_MIN = 3;
623     public static final int ID_TIME_IN_HR = 4;
624     public static final int ID_WINDOW_WIDTH = 5;
625     public static final int ID_WINDOW_HEIGHT = 6;
626     public static final int ID_COMPONENT_WIDTH = 7;
627     public static final int ID_COMPONENT_HEIGHT = 8;
628     public static final int ID_CALENDAR_MONTH = 9;
629     public static final int ID_OFFSET_TO_UTC = 10;
630     public static final int ID_WEEK_DAY = 11;
631     public static final int ID_DAY_OF_MONTH = 12;
632     public static final int ID_TOUCH_POS_X = 13;
633     public static final int ID_TOUCH_POS_Y = 14;
634 
635     public static final int ID_TOUCH_VEL_X = 15;
636     public static final int ID_TOUCH_VEL_Y = 16;
637 
638     public static final int ID_ACCELERATION_X = 17;
639     public static final int ID_ACCELERATION_Y = 18;
640     public static final int ID_ACCELERATION_Z = 19;
641 
642     public static final int ID_GYRO_ROT_X = 20;
643     public static final int ID_GYRO_ROT_Y = 21;
644     public static final int ID_GYRO_ROT_Z = 22;
645 
646     public static final int ID_MAGNETIC_X = 23;
647     public static final int ID_MAGNETIC_Y = 24;
648     public static final int ID_MAGNETIC_Z = 25;
649 
650     public static final int ID_LIGHT = 26;
651 
652     public static final int ID_DENSITY = 27;
653 
654     /** Defines when the last build was made */
655     public static final int ID_API_LEVEL = 28;
656 
657     /** Defines when the TOUCH EVENT HAPPENED */
658     public static final int ID_TOUCH_EVENT_TIME = 29;
659 
660     /** Animation time in seconds */
661     public static final int ID_ANIMATION_TIME = 30;
662 
663     /** The delta between current and last Frame */
664     public static final int ID_ANIMATION_DELTA_TIME = 31;
665 
666     public static final int ID_EPOCH_SECOND = 32;
667 
668     public static final int ID_FONT_SIZE = 33;
669 
670     public static final float FLOAT_DENSITY = Utils.asNan(ID_DENSITY);
671 
672     /** CONTINUOUS_SEC is seconds from midnight looping every hour 0-3600 */
673     public static final float FLOAT_CONTINUOUS_SEC = Utils.asNan(ID_CONTINUOUS_SEC);
674 
675     /** seconds run from Midnight=0 quantized to seconds hour 0..3599 */
676     public static final float FLOAT_TIME_IN_SEC = Utils.asNan(ID_TIME_IN_SEC);
677 
678     /** minutes run from Midnight=0 quantized to minutes 0..1439 */
679     public static final float FLOAT_TIME_IN_MIN = Utils.asNan(ID_TIME_IN_MIN);
680 
681     /** hours run from Midnight=0 quantized to Hours 0-23 */
682     public static final float FLOAT_TIME_IN_HR = Utils.asNan(ID_TIME_IN_HR);
683 
684     /** Moth of Year quantized to MONTHS 1-12. 1 = January */
685     public static final float FLOAT_CALENDAR_MONTH = Utils.asNan(ID_CALENDAR_MONTH);
686 
687     /** DAY OF THE WEEK 1-7. 1 = Monday */
688     public static final float FLOAT_WEEK_DAY = Utils.asNan(ID_WEEK_DAY);
689 
690     /** DAY OF THE MONTH 1-31 */
691     public static final float FLOAT_DAY_OF_MONTH = Utils.asNan(ID_DAY_OF_MONTH);
692 
693     public static final float FLOAT_WINDOW_WIDTH = Utils.asNan(ID_WINDOW_WIDTH);
694     public static final float FLOAT_WINDOW_HEIGHT = Utils.asNan(ID_WINDOW_HEIGHT);
695     public static final float FLOAT_COMPONENT_WIDTH = Utils.asNan(ID_COMPONENT_WIDTH);
696     public static final float FLOAT_COMPONENT_HEIGHT = Utils.asNan(ID_COMPONENT_HEIGHT);
697 
698     /** ID_OFFSET_TO_UTC is the offset from UTC in sec (typically / 3600f) */
699     public static final float FLOAT_OFFSET_TO_UTC = Utils.asNan(ID_OFFSET_TO_UTC);
700 
701     /** TOUCH_POS_X is the x position of the touch */
702     public static final float FLOAT_TOUCH_POS_X = Utils.asNan(ID_TOUCH_POS_X);
703 
704     /** TOUCH_POS_Y is the y position of the touch */
705     public static final float FLOAT_TOUCH_POS_Y = Utils.asNan(ID_TOUCH_POS_Y);
706 
707     /** TOUCH_VEL_X is the x velocity of the touch */
708     public static final float FLOAT_TOUCH_VEL_X = Utils.asNan(ID_TOUCH_VEL_X);
709 
710     /** TOUCH_VEL_Y is the x velocity of the touch */
711     public static final float FLOAT_TOUCH_VEL_Y = Utils.asNan(ID_TOUCH_VEL_Y);
712 
713     /** TOUCH_EVENT_TIME the time of the touch */
714     public static final float FLOAT_TOUCH_EVENT_TIME = Utils.asNan(ID_TOUCH_EVENT_TIME);
715 
716     /** Animation time in seconds */
717     public static final float FLOAT_ANIMATION_TIME = Utils.asNan(ID_ANIMATION_TIME);
718 
719     /** Animation time in seconds */
720     public static final float FLOAT_ANIMATION_DELTA_TIME = Utils.asNan(ID_ANIMATION_DELTA_TIME);
721 
722     /** X acceleration sensor value in M/s^2 */
723     public static final float FLOAT_ACCELERATION_X = Utils.asNan(ID_ACCELERATION_X);
724 
725     /** Y acceleration sensor value in M/s^2 */
726     public static final float FLOAT_ACCELERATION_Y = Utils.asNan(ID_ACCELERATION_Y);
727 
728     /** Z acceleration sensor value in M/s^2 */
729     public static final float FLOAT_ACCELERATION_Z = Utils.asNan(ID_ACCELERATION_Z);
730 
731     /** X Gyroscope rotation rate sensor value in radians/second */
732     public static final float FLOAT_GYRO_ROT_X = Utils.asNan(ID_GYRO_ROT_X);
733 
734     /** Y Gyroscope rotation rate sensor value in radians/second */
735     public static final float FLOAT_GYRO_ROT_Y = Utils.asNan(ID_GYRO_ROT_Y);
736 
737     /** Z Gyroscope rotation rate sensor value in radians/second */
738     public static final float FLOAT_GYRO_ROT_Z = Utils.asNan(ID_GYRO_ROT_Z);
739 
740     /** Ambient magnetic field in X. sensor value in micro-Tesla (uT) */
741     public static final float FLOAT_MAGNETIC_X = Utils.asNan(ID_MAGNETIC_X);
742 
743     /** Ambient magnetic field in Y. sensor value in micro-Tesla (uT) */
744     public static final float FLOAT_MAGNETIC_Y = Utils.asNan(ID_MAGNETIC_Y);
745 
746     /** Ambient magnetic field in Z. sensor value in micro-Tesla (uT) */
747     public static final float FLOAT_MAGNETIC_Z = Utils.asNan(ID_MAGNETIC_Z);
748 
749     /** Ambient light level in SI lux */
750     public static final float FLOAT_LIGHT = Utils.asNan(ID_LIGHT);
751 
752     /** When was this player built */
753     public static final float FLOAT_API_LEVEL = Utils.asNan(ID_API_LEVEL);
754 
755     /** The default font size */
756     public static final float FLOAT_FONT_SIZE = Utils.asNan(ID_FONT_SIZE);
757 
758     /** The time in seconds since the epoch. */
759     public static final long INT_EPOCH_SECOND = ((long) ID_EPOCH_SECOND) + 0x100000000L;
760 
761     ///////////////////////////////////////////////////////////////////////////////////////////////
762     // Click handling
763     ///////////////////////////////////////////////////////////////////////////////////////////////
764 
765     /**
766      * Is this a time id float
767      *
768      * @param fl the floatId to test
769      * @return true if it is a time id
770      */
isTime(float fl)771     public static boolean isTime(float fl) {
772         int value = Utils.idFromNan(fl);
773         return value >= ID_CONTINUOUS_SEC && value <= ID_DAY_OF_MONTH;
774     }
775 
776     /**
777      * get the time from a float id that indicates a type of time
778      *
779      * @param fl id of the type of time information requested
780      * @return various time information such as seconds or min
781      */
getTime(float fl)782     public static float getTime(float fl) {
783         LocalDateTime dateTime =
784                 LocalDateTime.now(ZoneId.systemDefault()); // TODO, pass in a timezone explicitly?
785         // This define the time in the format
786         // seconds run from Midnight=0 quantized to seconds hour 0..3599
787         // minutes run from Midnight=0 quantized to minutes 0..1439
788         // hours run from Midnight=0 quantized to Hours 0-23
789         // CONTINUOUS_SEC is seconds from midnight looping every hour 0-3600
790         // CONTINUOUS_SEC is accurate to milliseconds due to float precession
791         // ID_OFFSET_TO_UTC is the offset from UTC in sec (typically / 3600f)
792         int value = Utils.idFromNan(fl);
793         int month = dateTime.getMonth().getValue();
794         int hour = dateTime.getHour();
795         int minute = dateTime.getMinute();
796         int seconds = dateTime.getSecond();
797         int currentMinute = hour * 60 + minute;
798         int currentSeconds = minute * 60 + seconds;
799         float sec = currentSeconds + dateTime.getNano() * 1E-9f;
800         int day_week = dateTime.getDayOfWeek().getValue();
801 
802         ZoneId zone = ZoneId.systemDefault();
803         OffsetDateTime offsetDateTime = dateTime.atZone(zone).toOffsetDateTime();
804         ZoneOffset offset = offsetDateTime.getOffset();
805         switch (value) {
806             case ID_OFFSET_TO_UTC:
807                 return offset.getTotalSeconds();
808             case ID_CONTINUOUS_SEC:
809                 return sec;
810             case ID_TIME_IN_SEC:
811                 return currentSeconds;
812             case ID_TIME_IN_MIN:
813                 return currentMinute;
814             case ID_TIME_IN_HR:
815                 return hour;
816             case ID_CALENDAR_MONTH:
817             case ID_DAY_OF_MONTH:
818                 return month;
819             case ID_WEEK_DAY:
820                 return day_week;
821         }
822         return fl;
823     }
824 
825     /**
826      * Add a click area to the doc
827      *
828      * @param id the id of the click area
829      * @param contentDescription the content description of the click area
830      * @param left the left bounds of the click area
831      * @param top the top bounds of the click area
832      * @param right the right bounds of the click area
833      * @param bottom the
834      * @param metadataId the id of the metadata string
835      */
addClickArea( int id, int contentDescription, float left, float top, float right, float bottom, int metadataId)836     public abstract void addClickArea(
837             int id,
838             int contentDescription,
839             float left,
840             float top,
841             float right,
842             float bottom,
843             int metadataId);
844 
845     /** increments the count of operations executed in a pass */
incrementOpCount()846     public void incrementOpCount() {
847         mOpCount++;
848         if (mOpCount > MAX_OP_COUNT) {
849             throw new RuntimeException("Too many operations executed");
850         }
851     }
852 
853     /**
854      * Get the last Op Count and clear the count.
855      *
856      * @return the number of ops executed.
857      */
getLastOpCount()858     public int getLastOpCount() {
859         int count = mOpCount;
860         mOpCount = 0;
861         return count;
862     }
863 
864     /** Explicitly clear the operation counter */
clearLastOpCount()865     public void clearLastOpCount() {
866         mOpCount = 0;
867     }
868 }
869