1 /* 2 * Copyright (C) 2021 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.imsserviceentitlement.entitlement; 18 19 import android.content.Context; 20 21 import com.android.imsserviceentitlement.ts43.Ts43Constants.ResponseXmlAttributes; 22 import com.android.imsserviceentitlement.ts43.Ts43Constants.ResponseXmlNode; 23 import com.android.imsserviceentitlement.utils.XmlDoc; 24 import com.android.libraries.entitlement.ServiceEntitlement; 25 26 import java.util.Optional; 27 import java.util.concurrent.TimeUnit; 28 29 /** Provides the entitlement characteristic which stored from previous query. */ 30 public class EntitlementConfiguration { 31 /** Default value of version for VERS characteristic. */ 32 private static final int DEFAULT_VERSION = 0; 33 /** Default value of validity for VERS and TOKEN characteristics. */ 34 private static final long DEFAULT_VALIDITY = 0; 35 /** Default value of VoLTE/VoWifi/SMSoverIP entitlemenet status. */ 36 private static final int INCOMPATIBLE_STATE = 2; 37 38 private final EntitlementConfigurationsDataStore mConfigurationsDataStore; 39 40 private XmlDoc mXmlDoc = new XmlDoc(null); 41 EntitlementConfiguration(Context context, int subId)42 public EntitlementConfiguration(Context context, int subId) { 43 mConfigurationsDataStore = EntitlementConfigurationsDataStore.getInstance(context, subId); 44 mConfigurationsDataStore.get().ifPresent(rawXml -> mXmlDoc = new XmlDoc(rawXml)); 45 } 46 47 /** Update VERS characteristics with given version and validity. */ update(String rawXml)48 public void update(String rawXml) { 49 mConfigurationsDataStore.set(rawXml); 50 mXmlDoc = new XmlDoc(rawXml); 51 } 52 53 /** 54 * Returns VoLTE entitlement status from the {@link EntitlementConfigurationsDataStore}. If no 55 * data exist then return the default value {@link #INCOMPATIBLE_STATE}. 56 */ getVolteStatus()57 public int getVolteStatus() { 58 return mXmlDoc.get( 59 ResponseXmlNode.APPLICATION, 60 ResponseXmlAttributes.ENTITLEMENT_STATUS, 61 ServiceEntitlement.APP_VOLTE) 62 .map(Integer::parseInt) 63 .orElse(INCOMPATIBLE_STATE); 64 } 65 66 /** 67 * Returns VoWiFi entitlement status from the {@link EntitlementConfigurationsDataStore}. If no 68 * data exist then return the default value {@link #INCOMPATIBLE_STATE}. 69 */ getVoWifiStatus()70 public int getVoWifiStatus() { 71 return mXmlDoc.get( 72 ResponseXmlNode.APPLICATION, 73 ResponseXmlAttributes.ENTITLEMENT_STATUS, 74 ServiceEntitlement.APP_VOWIFI) 75 .map(Integer::parseInt) 76 .orElse(INCOMPATIBLE_STATE); 77 } 78 79 /** 80 * Returns SMSoIP entitlement status from the {@link EntitlementConfigurationsDataStore}. If no 81 * data exist then return the default value {@link #INCOMPATIBLE_STATE}. 82 */ getSmsOverIpStatus()83 public int getSmsOverIpStatus() { 84 return mXmlDoc.get( 85 ResponseXmlNode.APPLICATION, 86 ResponseXmlAttributes.ENTITLEMENT_STATUS, 87 ServiceEntitlement.APP_SMSOIP) 88 .map(Integer::parseInt) 89 .orElse(INCOMPATIBLE_STATE); 90 } 91 92 /** 93 * Returns token stored in the {@link EntitlementConfigurationsDataStore} if it is in validity 94 * period. Returns {@link Optional#empty()} if the token was expired or the value of token 95 * validity not positive. 96 */ getToken()97 public Optional<String> getToken() { 98 return isTokenInValidityPeriod() 99 ? mXmlDoc.get(ResponseXmlNode.TOKEN, ResponseXmlAttributes.TOKEN, null) 100 : Optional.empty(); 101 } 102 isTokenInValidityPeriod()103 private boolean isTokenInValidityPeriod() { 104 long queryTimeMillis = mConfigurationsDataStore.getQueryTimeMillis(); 105 long tokenValidityMillis = TimeUnit.SECONDS.toMillis(getTokenValidity()); 106 107 if (queryTimeMillis <= 0) { 108 // False if the query time not been set. 109 return false; 110 } 111 112 // When the token validity is set to 0, the Entitlement Client shall store the token without 113 // any limitation of duration. 114 if (tokenValidityMillis <= 0) { 115 return true; 116 } 117 118 return (System.currentTimeMillis() - queryTimeMillis) < tokenValidityMillis; 119 } 120 121 /** 122 * Returns the validity of the token, in seconds. The validity is counted from the time it is 123 * received by the client. If no data exist then returns default value 0. 124 */ getTokenValidity()125 public long getTokenValidity() { 126 return mXmlDoc.get( 127 ResponseXmlNode.TOKEN, 128 ResponseXmlAttributes.VALIDITY, 129 null) 130 .map(Long::parseLong) 131 .orElse(DEFAULT_VALIDITY); 132 } 133 134 /** Returns version stored in the {@link EntitlementCharacteristicDataStore}. */ getVersion()135 public Optional<String> getVersion() { 136 return mXmlDoc.get(ResponseXmlNode.VERS, ResponseXmlAttributes.VERSION, null); 137 } 138 139 /** 140 * Returns the validity of the version, in seconds. The validity is counted from the time it is 141 * received by the client. If no data exist then returns default value 0. 142 */ getVersValidity()143 public long getVersValidity() { 144 return mXmlDoc.get( 145 ResponseXmlNode.VERS, 146 ResponseXmlAttributes.VALIDITY, 147 null) 148 .map(Long::parseLong) 149 .orElse(DEFAULT_VALIDITY); 150 } 151 152 public enum ClientBehavior { 153 /** Unknown behavior. */ 154 UNKNOWN_BEHAVIOR, 155 /** Entitlement data is valid during validity seconds. */ 156 VALID_DURING_VALIDITY, 157 /** Entitlement data is valid without any limitation of duration. */ 158 VALID_WITHOUT_DURATION, 159 /** Entitlement data has to be reset to default configuration */ 160 NEEDS_TO_RESET, 161 /** 162 * Entitlement data has to be reset to default configuration except for version and 163 * validity. The Entitlement Client shall not perform client configuration requests anymore 164 * for the services just configured. 165 */ 166 NEEDS_TO_RESET_EXCEPT_VERS, 167 /** 168 * entitlement data has to be reset to default configuration except for version and 169 * validity. The Entitlement Client shall not perform client configuration requests anymore 170 * for the services just configured, until the end-user switches the setting to On. 171 */ 172 NEEDS_TO_RESET_EXCEPT_VERS_UNTIL_SETTING_ON, 173 } 174 175 /** Returns {@link ClientBehavior} for the service to be configured. */ entitlementValidation()176 public ClientBehavior entitlementValidation() { 177 int version = mXmlDoc.get( 178 ResponseXmlNode.VERS, 179 ResponseXmlAttributes.VERSION, 180 null) 181 .map(Integer::parseInt) 182 .orElse(DEFAULT_VERSION); 183 long validity = mXmlDoc.get( 184 ResponseXmlNode.VERS, 185 ResponseXmlAttributes.VALIDITY, 186 null) 187 .map(Long::parseLong) 188 .orElse(DEFAULT_VALIDITY); 189 190 if (version > 0 && validity > 0) { 191 return ClientBehavior.VALID_DURING_VALIDITY; 192 } else if (version > 0 && validity == 0) { 193 return ClientBehavior.VALID_WITHOUT_DURATION; 194 } else if (version == 0 && validity == 0) { 195 return ClientBehavior.NEEDS_TO_RESET; 196 } else if (version == -1 && validity == -1) { 197 return ClientBehavior.NEEDS_TO_RESET_EXCEPT_VERS; 198 } else if (version == -2 && validity == -2) { 199 return ClientBehavior.NEEDS_TO_RESET_EXCEPT_VERS_UNTIL_SETTING_ON; 200 } 201 202 // Should never reach. 203 return ClientBehavior.UNKNOWN_BEHAVIOR; 204 } 205 206 /** 207 * Removes the stored configuration and reverts to the default configuration when: 208 * <ul> 209 * <li>on SIM card change 210 * <li>on menu Factory reset 211 * <li>if a service is barred by the Service Provider (i.e. configuration version set to 0, 212 * -1, -2). In that case, version and validity are not reset 213 * </ul> 214 */ reset()215 public void reset() { 216 // Default configuration of the Characteristics: 217 // - VERS.version = 0 218 // - VERS.validity = 0 219 // - TOKEN.token = null (i.e. no value assigned) 220 // - TOKEN.validity =0 221 // - VoLTE.EntitlementStatus=2 (INCOMPATIBLE_STATE) 222 // - VoWiFi.EntitlementStatus=2 (INCOMPATIBLE_STATE) 223 // - SMSoIP.EntitlementStatus=2 (INCOMPATIBLE_STATE) 224 update(null); 225 } 226 227 /** Reverts to the default configurations except the version and validity. */ resetConfigsExceptVers()228 public void resetConfigsExceptVers() { 229 String rawXml = 230 "<wap-provisioningdoc version=\"1.1\">" 231 + " <characteristic type=\"VERS\">" 232 + " <parm name=\"version\" value=\"" + getVersion().get() + "\"/>" 233 + " <parm name=\"validity\" value=\"" + getVersValidity() + "\"/>" 234 + " </characteristic>" 235 + " <characteristic type=\"TOKEN\">" 236 + " <parm name=\"token\" value=\"\"/>" 237 + " <parm name=\"validity\" value=\"0\"/>" 238 + " </characteristic>" 239 + " <characteristic type=\"APPLICATION\">" 240 + " <parm name=\"AppID\" value=\"ap2003\"/>" 241 + " <parm name=\"EntitlementStatus\" value=\"2\"/>" 242 + " </characteristic>" 243 + " <characteristic type=\"APPLICATION\">" 244 + " <parm name=\"AppID\" value=\"ap2004\"/>" 245 + " <parm name=\"EntitlementStatus\" value=\"2\"/>" 246 + " </characteristic>" 247 + " <characteristic type=\"APPLICATION\">" 248 + " <parm name=\"AppID\" value=\"ap2005\"/>" 249 + " <parm name=\"EntitlementStatus\" value=\"2\"/>" 250 + " </characteristic>" 251 + "</wap-provisioningdoc>"; 252 update(rawXml); 253 } 254 } 255