1 /*
2  * Copyright (C) 2023 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 static com.android.internal.widget.remotecompose.core.RemoteContext.ID_CONTINUOUS_SEC;
19 import static com.android.internal.widget.remotecompose.core.RemoteContext.ID_TIME_IN_MIN;
20 import static com.android.internal.widget.remotecompose.core.RemoteContext.ID_TIME_IN_SEC;
21 import static com.android.internal.widget.remotecompose.core.RemoteContext.ID_WINDOW_HEIGHT;
22 import static com.android.internal.widget.remotecompose.core.RemoteContext.ID_WINDOW_WIDTH;
23 
24 import com.android.internal.widget.remotecompose.core.operations.utilities.IntMap;
25 
26 import java.util.ArrayList;
27 import java.util.HashMap;
28 
29 /**
30  * Represents runtime state for a RemoteCompose document
31  * State includes things like the value of variables
32  */
33 public class RemoteComposeState {
34     public static final int START_ID = 42;
35     private static final int MAX_FLOATS = 500;
36     private final IntMap<Object> mIntDataMap = new IntMap<>();
37     private final IntMap<Boolean> mIntWrittenMap = new IntMap<>();
38     private final HashMap<Object, Integer> mDataIntMap = new HashMap();
39     private final float[] mFloatMap = new float[MAX_FLOATS]; // efficient cache
40     private final int[] mColorMap = new int[MAX_FLOATS]; // efficient cache
41     private int mNextId = START_ID;
42 
43     {
44         for (int i = 0; i < mFloatMap.length; i++) {
45             mFloatMap[i] = Float.NaN;
46         }
47     }
48 
49     /**
50      * Get Object based on id. The system will cache things like bitmaps
51      * Paths etc. They can be accessed with this command
52      * @param id
53      * @return
54      */
getFromId(int id)55     public Object getFromId(int id) {
56         return mIntDataMap.get(id);
57     }
58 
59     /**
60      * true if the cache contain this id
61      * @param id
62      * @return
63      */
containsId(int id)64     public boolean containsId(int id) {
65         return mIntDataMap.get(id) != null;
66     }
67 
68     /**
69      * Return the id of an item from the cache.
70      */
dataGetId(Object image)71     public int dataGetId(Object image) {
72         Integer res = mDataIntMap.get(image);
73         if (res == null) {
74             return -1;
75         }
76         return res;
77     }
78 
79     /**
80      * Add an image to the cache. Generates an id for the image and adds it to the cache based on
81      * that id.
82      */
cache(Object image)83     public int cache(Object image) {
84         int id = nextId();
85         mDataIntMap.put(image, id);
86         mIntDataMap.put(id, image);
87         return id;
88     }
89 
90     /**
91      * Insert an item in the cache
92      */
cache(int id, Object item)93     public void cache(int id, Object item) {
94         mDataIntMap.put(item, id);
95         mIntDataMap.put(id, item);
96     }
97 
98     /**
99      * Insert an item in the cache
100      */
update(int id, Object item)101     public void update(int id, Object item) {
102         mDataIntMap.remove(mIntDataMap.get(id));
103         mDataIntMap.put(item, id);
104         mIntDataMap.put(id, item);
105     }
106 
107     /**
108      * Insert an item in the cache
109      */
cacheFloat(float item)110     public int cacheFloat(float item) {
111         int id = nextId();
112         mFloatMap[id] = item;
113         return id;
114     }
115 
116     /**
117      * Insert an item in the cache
118      */
cacheFloat(int id, float item)119     public void cacheFloat(int id, float item) {
120         mFloatMap[id] = item;
121     }
122 
123     /**
124      * Insert an item in the cache
125      */
updateFloat(int id, float item)126     public void updateFloat(int id, float item) {
127         mFloatMap[id] = item;
128     }
129 
130     /**
131      * get float
132      */
getFloat(int id)133     public float getFloat(int id) {
134         return mFloatMap[id];
135     }
136 
137     /**
138      * Get the float value
139      *
140      * @param id
141      * @return
142      */
getColor(int id)143     public int getColor(int id) {
144         return mColorMap[id];
145     }
146 
147     /**
148      * Modify the color at id.
149      * @param id
150      * @param color
151      */
updateColor(int id, int color)152     public void updateColor(int id, int color) {
153         mColorMap[id] = color;
154     }
155 
156 
157     /**
158      * Method to determine if a cached value has been written to the documents WireBuffer based on
159      * its id.
160      */
wasNotWritten(int id)161     public boolean wasNotWritten(int id) {
162         return !mIntWrittenMap.get(id);
163     }
164 
165     /**
166      * Method to mark that a value, represented by its id, has been written to the WireBuffer
167      */
markWritten(int id)168     public void markWritten(int id) {
169         mIntWrittenMap.put(id, true);
170     }
171 
172     /**
173      * Clear the record of the values that have been written to the WireBuffer.
174      */
reset()175     void reset() {
176         mIntWrittenMap.clear();
177     }
178 
179     /**
180      * Get the next available id
181      * @return
182      */
nextId()183     public int nextId() {
184         return mNextId++;
185     }
186 
187     /**
188      * Set the next id
189      * @param id
190      */
setNextId(int id)191     public void setNextId(int id) {
192         mNextId = id;
193     }
194 
195     IntMap<ArrayList<VariableSupport>> mVarListeners = new IntMap<>();
196     ArrayList<VariableSupport> mAllVarListeners = new ArrayList<>();
197 
add(int id, VariableSupport variableSupport)198     private void add(int id, VariableSupport variableSupport) {
199         ArrayList<VariableSupport> v = mVarListeners.get(id);
200         if (v == null) {
201             v = new ArrayList<VariableSupport>();
202             mVarListeners.put(id, v);
203         }
204         v.add(variableSupport);
205         mAllVarListeners.add(variableSupport);
206     }
207 
208     /**
209      * Commands that listen to variables add themselves.
210      * @param id
211      * @param variableSupport
212      */
listenToVar(int id, VariableSupport variableSupport)213     public void listenToVar(int id, VariableSupport variableSupport) {
214         add(id, variableSupport);
215     }
216 
217     /**
218      * List of Commands that need to be updated
219      * @param context
220      * @return
221      */
getOpsToUpdate(RemoteContext context)222     public int getOpsToUpdate(RemoteContext context) {
223         for (VariableSupport vs : mAllVarListeners) {
224             vs.updateVariables(context);
225         }
226         if (mVarListeners.get(ID_CONTINUOUS_SEC) != null) {
227             return 1;
228         }
229         if (mVarListeners.get(ID_TIME_IN_SEC) != null) {
230             return 1000;
231         }
232         if (mVarListeners.get(ID_TIME_IN_MIN) != null) {
233             return 1000 * 60;
234         }
235         return -1;
236     }
237 
238     /**
239      * Set the width of the overall document on screen.
240      * @param width
241      */
setWindowWidth(float width)242     public void setWindowWidth(float width) {
243         updateFloat(ID_WINDOW_WIDTH, width);
244     }
245 
246     /**
247      * Set the width of the overall document on screen.
248      * @param height
249      */
setWindowHeight(float height)250     public void setWindowHeight(float height) {
251         updateFloat(ID_WINDOW_HEIGHT, height);
252     }
253 
254 }
255