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