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 17 package com.android.adservices.service.ui.util; 18 19 import static android.adservices.common.AdServicesCommonManager.MODULE_STATE_UNKNOWN; 20 import static android.adservices.common.AdServicesCommonManager.Module; 21 import static android.adservices.common.AdServicesCommonManager.ModuleState; 22 import static android.adservices.common.AdServicesModuleUserChoice.USER_CHOICE_UNKNOWN; 23 24 import android.adservices.common.AdServicesCommonManager; 25 import android.adservices.common.AdServicesModuleUserChoice; 26 import android.adservices.common.AdServicesModuleUserChoice.ModuleUserChoiceCode; 27 import android.adservices.common.Module.ModuleCode; 28 import android.util.SparseIntArray; 29 30 import com.android.adservices.LogUtil; 31 32 import com.google.common.base.Strings; 33 34 import org.json.JSONArray; 35 import org.json.JSONException; 36 import org.json.JSONObject; 37 38 import java.io.Serializable; 39 40 /** 41 * Container object that has enrollment data. Should not be used as storage. This is only a helper 42 * class to more easily read/write enrollment data. 43 */ 44 public class EnrollmentData implements Serializable { 45 // IMPORTANT: New data must be serialized/deserialized correctly to be stored 46 private final SparseIntArray mModuleStates = new SparseIntArray(); 47 private final SparseIntArray mUserChoices = new SparseIntArray(); 48 49 private static final String MODULE_STATE_JSON_KEY = "mModuleStates"; 50 51 private static final String USER_CHOICE_JSON_KEY = "mUserChoices"; 52 53 /** 54 * Serializes module enrollment state data to string. 55 * 56 * @param data Data to serialize. 57 * @return Serialized string. 58 */ serialize(EnrollmentData data)59 public static String serialize(EnrollmentData data) { 60 JSONObject jsonObject = new JSONObject(); 61 String enrollmentDataStr = ""; 62 try { 63 // Serialize mModuleStates 64 JSONArray moduleStatesArray = getJsonArrFromSparseArr(data.mModuleStates); 65 jsonObject.put(MODULE_STATE_JSON_KEY, moduleStatesArray); 66 67 // Serialize mUserChoices 68 JSONArray userChoicesArray = getJsonArrFromSparseArr(data.mUserChoices); 69 jsonObject.put(USER_CHOICE_JSON_KEY, userChoicesArray); 70 enrollmentDataStr = jsonObject.toString(); 71 } catch (JSONException e) { 72 LogUtil.e("Enrollment Data serializing error:" + e); 73 } 74 return enrollmentDataStr; 75 } 76 77 /** 78 * Deserializes module enrolment state data from string. 79 * 80 * @param string String to deserialize. 81 * @return Object with enrollment data. 82 */ deserialize(String jsonStr)83 public static EnrollmentData deserialize(String jsonStr) { 84 EnrollmentData enrollmentData = new EnrollmentData(); 85 if (Strings.isNullOrEmpty(jsonStr)) { 86 return enrollmentData; 87 } 88 JSONObject jsonObject; 89 try { 90 jsonObject = new JSONObject(jsonStr); 91 // Deserialize mModuleStates 92 JSONArray moduleStatesArray = jsonObject.getJSONArray(MODULE_STATE_JSON_KEY); 93 populateSparseArrFromJsonArr(moduleStatesArray, enrollmentData.mModuleStates); 94 95 // Deserialize mUserChoices 96 JSONArray userChoicesArray = jsonObject.getJSONArray(USER_CHOICE_JSON_KEY); 97 populateSparseArrFromJsonArr(userChoicesArray, enrollmentData.mUserChoices); 98 } catch (JSONException e) { 99 LogUtil.e("Enrollment Data deserializing error:" + e); 100 } 101 return enrollmentData; 102 } 103 104 /** 105 * Gets all the module states currently stored. 106 * 107 * @return all module states. 108 */ getModuleStates()109 public SparseIntArray getModuleStates() { 110 return mModuleStates; 111 } 112 113 /** 114 * Gets the module state for the given module. If null, then returns {@link 115 * AdServicesCommonManager#MODULE_STATE_UNKNOWN}. 116 * 117 * @param key Key of desired module. 118 * @return module state for given module. 119 */ 120 @ModuleState getModuleState(@oduleCode int key)121 public int getModuleState(@ModuleCode int key) { 122 return mModuleStates.get(key, MODULE_STATE_UNKNOWN); 123 } 124 125 /** 126 * Stores the state for the given module. 127 * 128 * @param module Code for desired module. 129 * @param state Module choice object to update in enrollment data. 130 */ putModuleState(@odule int module, @ModuleState int state)131 public void putModuleState(@Module int module, @ModuleState int state) { 132 mModuleStates.put(module, state); 133 } 134 135 /** 136 * Gets all the user choices currently stored. 137 * 138 * @return all user choices. 139 */ 140 @ModuleUserChoiceCode getUserChoices()141 public SparseIntArray getUserChoices() { 142 return mUserChoices; 143 } 144 145 /** 146 * Gets the user choice for the given module. If null, then returns {@link 147 * AdServicesModuleUserChoice#USER_CHOICE_UNKNOWN}. 148 * 149 * @param key Key of desired module. 150 * @return User choice for given module. 151 */ 152 @ModuleUserChoiceCode getUserChoice(@oduleCode int key)153 public int getUserChoice(@ModuleCode int key) { 154 return mUserChoices.get(key, USER_CHOICE_UNKNOWN); 155 } 156 157 /** 158 * Stores the user choice for the given module. 159 * 160 * @param userChoice User choice object to update in enrollment data. 161 */ putUserChoice(AdServicesModuleUserChoice userChoice)162 public void putUserChoice(AdServicesModuleUserChoice userChoice) { 163 putUserChoice(userChoice.getModule(), userChoice.getUserChoice()); 164 } 165 166 /** 167 * Stores the user choice for the given module code. 168 * 169 * @param moduleCode Code for desired module. 170 * @param userChoiceCode User choice to store. 171 */ putUserChoice( @oduleCode int moduleCode, @ModuleUserChoiceCode int userChoiceCode)172 public void putUserChoice( 173 @ModuleCode int moduleCode, @ModuleUserChoiceCode int userChoiceCode) { 174 mUserChoices.put(moduleCode, userChoiceCode); 175 } 176 getJsonArrFromSparseArr(SparseIntArray inputArr)177 private static JSONArray getJsonArrFromSparseArr(SparseIntArray inputArr) throws JSONException { 178 JSONArray jsonArr = new JSONArray(); 179 for (int i = 0; i < inputArr.size(); i++) { 180 JSONObject jsonObj = new JSONObject(); 181 jsonObj.put(String.valueOf(inputArr.keyAt(i)), String.valueOf(inputArr.valueAt(i))); 182 183 jsonArr.put(jsonObj); 184 } 185 return jsonArr; 186 } 187 populateSparseArrFromJsonArr(JSONArray jsonArr, SparseIntArray outputArr)188 private static void populateSparseArrFromJsonArr(JSONArray jsonArr, SparseIntArray outputArr) 189 throws JSONException { 190 for (int i = 0; i < jsonArr.length(); i++) { 191 JSONObject jsonObj = jsonArr.getJSONObject(i); 192 for (int j = 0; j < jsonObj.names().length(); j++) { 193 String key = jsonObj.names().getString(j); 194 outputArr.put(Integer.parseInt(key), Integer.parseInt(jsonObj.getString(key))); 195 } 196 } 197 } 198 } 199