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 com.android.internal.widget.remotecompose.core.operations.FloatExpression;
19 import com.android.internal.widget.remotecompose.core.operations.ShaderData;
20 import com.android.internal.widget.remotecompose.core.operations.Theme;
21 import com.android.internal.widget.remotecompose.core.operations.Utils;
22 
23 /**
24  * Specify an abstract context used to playback RemoteCompose documents
25  *
26  * This allows us to intercept the different operations in a document and react to them.
27  *
28  * We also contain a PaintContext, so that any operation can draw as needed.
29  */
30 public abstract class RemoteContext {
31     protected CoreDocument mDocument;
32     public RemoteComposeState mRemoteComposeState;
33     long mStart = System.nanoTime(); // todo This should be set at a hi level
34     protected PaintContext mPaintContext = null;
35     ContextMode mMode = ContextMode.UNSET;
36 
37     boolean mDebug = false;
38     private int mTheme = Theme.UNSPECIFIED;
39 
40     public float mWidth = 0f;
41     public float mHeight = 0f;
42 
43     /**
44      * Load a path under an id.
45      * Paths can be use in clip drawPath and drawTweenPath
46      * @param instanceId
47      * @param floatPath
48      */
loadPathData(int instanceId, float[] floatPath)49     public abstract void loadPathData(int instanceId, float[] floatPath);
50 
51     /**
52      * Associate a name with a give id.
53      *
54      * @param varName
55      * @param varId
56      * @param varType
57      */
loadVariableName(String varName, int varId, int varType)58     public abstract void loadVariableName(String varName, int varId, int varType);
59 
60     /**
61      * Save a color under a given id
62      * @param id
63      * @param color
64      */
loadColor(int id, int color)65     public abstract void loadColor(int id, int color);
66 
67     /**
68      * gets the time animation clock as float in seconds
69      * @return a monotonic time in seconds (arbitrary zero point)
70      */
getAnimationTime()71     public float getAnimationTime() {
72         return (System.nanoTime() - mStart) * 1E-9f;
73     }
74 
75 
76     /**
77      * The context can be used in a few different mode, allowing operations to skip being executed:
78      * - UNSET : all operations will get executed
79      * - DATA : only operations dealing with DATA (eg loading a bitmap) should execute
80      * - PAINT : only operations painting should execute
81      */
82     public enum  ContextMode {
83         UNSET, DATA, PAINT
84     }
85 
getTheme()86     public int getTheme() {
87         return mTheme;
88     }
89 
setTheme(int theme)90     public void setTheme(int theme) {
91         this.mTheme = theme;
92     }
93 
getMode()94     public ContextMode getMode() {
95         return mMode;
96     }
97 
setMode(ContextMode mode)98     public void setMode(ContextMode mode) {
99         this.mMode = mode;
100     }
101 
getPaintContext()102     public PaintContext getPaintContext() {
103         return mPaintContext;
104     }
105 
setPaintContext(PaintContext paintContext)106     public void setPaintContext(PaintContext paintContext) {
107         this.mPaintContext = paintContext;
108     }
109 
getDocument()110     public CoreDocument getDocument() {
111         return mDocument;
112     }
113 
isDebug()114     public boolean isDebug() {
115         return mDebug;
116     }
117 
setDebug(boolean debug)118     public void setDebug(boolean debug) {
119         this.mDebug = debug;
120     }
121 
setDocument(CoreDocument document)122     public void setDocument(CoreDocument document) {
123         this.mDocument = document;
124     }
125 
126     ///////////////////////////////////////////////////////////////////////////////////////////////
127     // Operations
128     ///////////////////////////////////////////////////////////////////////////////////////////////
129 
header(int majorVersion, int minorVersion, int patchVersion, int width, int height, long capabilities )130     public void header(int majorVersion, int minorVersion, int patchVersion,
131                        int width, int height, long capabilities
132     ) {
133         mRemoteComposeState.setWindowWidth(width);
134         mRemoteComposeState.setWindowHeight(height);
135         mDocument.setVersion(majorVersion, minorVersion, patchVersion);
136         mDocument.setWidth(width);
137         mDocument.setHeight(height);
138         mDocument.setRequiredCapabilities(capabilities);
139     }
140 
141     /**
142      * Sets the way the player handles the content
143      *
144      * @param scroll set the horizontal behavior (NONE|SCROLL_HORIZONTAL|SCROLL_VERTICAL)
145      * @param alignment set the alignment of the content (TOP|CENTER|BOTTOM|START|END)
146      * @param sizing set the type of sizing for the content (NONE|SIZING_LAYOUT|SIZING_SCALE)
147      * @param mode set the mode of sizing, either LAYOUT modes or SCALE modes
148      *             the LAYOUT modes are:
149      *             - LAYOUT_MATCH_PARENT
150      *             - LAYOUT_WRAP_CONTENT
151      *             or adding an horizontal mode and a vertical mode:
152      *             - LAYOUT_HORIZONTAL_MATCH_PARENT
153      *             - LAYOUT_HORIZONTAL_WRAP_CONTENT
154      *             - LAYOUT_HORIZONTAL_FIXED
155      *             - LAYOUT_VERTICAL_MATCH_PARENT
156      *             - LAYOUT_VERTICAL_WRAP_CONTENT
157      *             - LAYOUT_VERTICAL_FIXED
158      *             The LAYOUT_*_FIXED modes will use the intrinsic document size
159      */
setRootContentBehavior(int scroll, int alignment, int sizing, int mode)160     public void setRootContentBehavior(int scroll, int alignment, int sizing, int mode) {
161         mDocument.setRootContentBehavior(scroll, alignment, sizing, mode);
162     }
163 
164     /**
165      * Set a content description for the document
166      * @param contentDescriptionId the text id pointing at the description
167      */
setDocumentContentDescription(int contentDescriptionId)168     public void setDocumentContentDescription(int contentDescriptionId) {
169         String contentDescription = (String) mRemoteComposeState.getFromId(contentDescriptionId);
170         mDocument.setContentDescription(contentDescription);
171     }
172 
173     ///////////////////////////////////////////////////////////////////////////////////////////////
174     // Data handling
175     ///////////////////////////////////////////////////////////////////////////////////////////////
176 
177     /**
178      * Save a bitmap under an imageId
179      * @param imageId
180      * @param width
181      * @param height
182      * @param bitmap
183      */
loadBitmap(int imageId, int width, int height, byte[] bitmap)184     public abstract void loadBitmap(int imageId, int width, int height, byte[] bitmap);
185 
186     /**
187      * Save a string under a given id
188      * @param id
189      * @param text
190      */
loadText(int id, String text)191     public abstract void loadText(int id, String text);
192 
193     /**
194      * Get a string given an id
195      * @param id
196      * @return
197      */
getText(int id)198     public abstract String getText(int id);
199 
200     /**
201      * Load a float
202      * @param id
203      * @param value
204      */
loadFloat(int id, float value)205     public abstract void loadFloat(int id, float value);
206 
207     /**
208      * Load an animated float associated with an id
209      * Todo: Remove?
210      * @param id
211      * @param animatedFloat
212      */
loadAnimatedFloat(int id, FloatExpression animatedFloat)213     public abstract void loadAnimatedFloat(int id, FloatExpression animatedFloat);
214 
215     /**
216      * Save a shader under and ID
217      * @param id
218      * @param value
219      */
loadShader(int id, ShaderData value)220     public abstract void loadShader(int id, ShaderData value);
221 
222     /**
223      * Get a float given an id
224      * @param id
225      * @return
226      */
getFloat(int id)227     public abstract float getFloat(int id);
228 
229     /**
230      * Get the color given and ID
231      * @param id
232      * @return
233      */
getColor(int id)234     public abstract int getColor(int id);
235 
236     /**
237      * called to notify system that a command is interested in a variable
238      * @param id
239      * @param variableSupport
240      */
listensTo(int id, VariableSupport variableSupport)241     public abstract void listensTo(int id, VariableSupport variableSupport);
242 
243     /**
244      * Notify commands with variables have changed
245      * @return
246      */
updateOps()247     public abstract int updateOps();
248 
249     /**
250      * Get a shader given the id
251      * @param id
252      * @return
253      */
getShader(int id)254     public abstract ShaderData getShader(int id);
255 
256     public static final int ID_CONTINUOUS_SEC = 1;
257     public static final int ID_TIME_IN_SEC = 2;
258     public static final int ID_TIME_IN_MIN = 3;
259     public static final int ID_TIME_IN_HR = 4;
260     public static final int ID_WINDOW_WIDTH = 5;
261     public static final int ID_WINDOW_HEIGHT = 6;
262     public static final int ID_COMPONENT_WIDTH = 7;
263     public static final int ID_COMPONENT_HEIGHT = 8;
264     public static final int ID_CALENDAR_MONTH = 9;
265 
266     public static final float FLOAT_CONTINUOUS_SEC = Utils.asNan(ID_CONTINUOUS_SEC);
267     public static final float FLOAT_TIME_IN_SEC = Utils.asNan(ID_TIME_IN_SEC);
268     public static final float FLOAT_TIME_IN_MIN = Utils.asNan(ID_TIME_IN_MIN);
269     public static final float FLOAT_TIME_IN_HR = Utils.asNan(ID_TIME_IN_HR);
270     public static final float FLOAT_CALENDAR_MONTH = Utils.asNan(ID_CALENDAR_MONTH);
271     public static final float FLOAT_WINDOW_WIDTH = Utils.asNan(ID_WINDOW_WIDTH);
272     public static final float FLOAT_WINDOW_HEIGHT = Utils.asNan(ID_WINDOW_HEIGHT);
273     public static final float FLOAT_COMPONENT_WIDTH = Utils.asNan(ID_COMPONENT_WIDTH);
274     public static final float FLOAT_COMPONENT_HEIGHT = Utils.asNan(ID_COMPONENT_HEIGHT);
275     ///////////////////////////////////////////////////////////////////////////////////////////////
276     // Click handling
277     ///////////////////////////////////////////////////////////////////////////////////////////////
addClickArea( int id, int contentDescription, float left, float top, float right, float bottom, int metadataId )278     public abstract void addClickArea(
279             int id,
280             int contentDescription,
281             float left,
282             float top,
283             float right,
284             float bottom,
285             int metadataId
286     );
287 }
288 
289