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 /** 135 * Returns version stored in the {@link EntitlementCharacteristicDataStore}. 136 * If no data exists then return the default value {@link #DEFAULT_VERSION}. 137 */ getVersion()138 public String getVersion() { 139 return mXmlDoc.get(ResponseXmlNode.VERS, ResponseXmlAttributes.VERSION, null) 140 .orElse(String.valueOf(DEFAULT_VERSION)); 141 } 142 143 /** 144 * Returns the validity of the version, in seconds. The validity is counted from the time it is 145 * received by the client. If no data exist then returns default value 0. 146 */ getVersValidity()147 public long getVersValidity() { 148 return mXmlDoc.get( 149 ResponseXmlNode.VERS, 150 ResponseXmlAttributes.VALIDITY, 151 null) 152 .map(Long::parseLong) 153 .orElse(DEFAULT_VALIDITY); 154 } 155 156 public enum ClientBehavior { 157 /** Unknown behavior. */ 158 UNKNOWN_BEHAVIOR, 159 /** Entitlement data is valid during validity seconds. */ 160 VALID_DURING_VALIDITY, 161 /** Entitlement data is valid without any limitation of duration. */ 162 VALID_WITHOUT_DURATION, 163 /** Entitlement data has to be reset to default configuration */ 164 NEEDS_TO_RESET, 165 /** 166 * Entitlement data has to be reset to default configuration except for version and 167 * validity. The Entitlement Client shall not perform client configuration requests anymore 168 * for the services just configured. 169 */ 170 NEEDS_TO_RESET_EXCEPT_VERS, 171 /** 172 * entitlement data has to be reset to default configuration except for version and 173 * validity. The Entitlement Client shall not perform client configuration requests anymore 174 * for the services just configured, until the end-user switches the setting to On. 175 */ 176 NEEDS_TO_RESET_EXCEPT_VERS_UNTIL_SETTING_ON, 177 } 178 179 /** Returns {@link ClientBehavior} for the service to be configured. */ entitlementValidation()180 public ClientBehavior entitlementValidation() { 181 int version = mXmlDoc.get( 182 ResponseXmlNode.VERS, 183 ResponseXmlAttributes.VERSION, 184 null) 185 .map(Integer::parseInt) 186 .orElse(DEFAULT_VERSION); 187 long validity = mXmlDoc.get( 188 ResponseXmlNode.VERS, 189 ResponseXmlAttributes.VALIDITY, 190 null) 191 .map(Long::parseLong) 192 .orElse(DEFAULT_VALIDITY); 193 194 if (version > 0 && validity > 0) { 195 return ClientBehavior.VALID_DURING_VALIDITY; 196 } else if (version > 0 && validity == 0) { 197 return ClientBehavior.VALID_WITHOUT_DURATION; 198 } else if (version == 0 && validity == 0) { 199 return ClientBehavior.NEEDS_TO_RESET; 200 } else if (version == -1 && validity == -1) { 201 return ClientBehavior.NEEDS_TO_RESET_EXCEPT_VERS; 202 } else if (version == -2 && validity == -2) { 203 return ClientBehavior.NEEDS_TO_RESET_EXCEPT_VERS_UNTIL_SETTING_ON; 204 } 205 206 // Should never reach. 207 return ClientBehavior.UNKNOWN_BEHAVIOR; 208 } 209 210 /** 211 * Removes the stored configuration and reverts to the default configuration when: 212 * <ul> 213 * <li>on SIM card change 214 * <li>on menu Factory reset 215 * <li>if a service is barred by the Service Provider (i.e. configuration version set to 0, 216 * -1, -2). In that case, version and validity are not reset 217 * </ul> 218 */ reset()219 public void reset() { 220 // Default configuration of the Characteristics: 221 // - VERS.version = 0 222 // - VERS.validity = 0 223 // - TOKEN.token = null (i.e. no value assigned) 224 // - TOKEN.validity =0 225 // - VoLTE.EntitlementStatus=2 (INCOMPATIBLE_STATE) 226 // - VoWiFi.EntitlementStatus=2 (INCOMPATIBLE_STATE) 227 // - SMSoIP.EntitlementStatus=2 (INCOMPATIBLE_STATE) 228 update(null); 229 } 230 231 /** Reverts to the default configurations except the version and validity. */ resetConfigsExceptVers()232 public void resetConfigsExceptVers() { 233 String rawXml = 234 "<wap-provisioningdoc version=\"1.1\">" 235 + " <characteristic type=\"VERS\">" 236 + " <parm name=\"version\" value=\"" + getVersion() + "\"/>" 237 + " <parm name=\"validity\" value=\"" + getVersValidity() + "\"/>" 238 + " </characteristic>" 239 + " <characteristic type=\"TOKEN\">" 240 + " <parm name=\"token\" value=\"\"/>" 241 + " <parm name=\"validity\" value=\"0\"/>" 242 + " </characteristic>" 243 + " <characteristic type=\"APPLICATION\">" 244 + " <parm name=\"AppID\" value=\"ap2003\"/>" 245 + " <parm name=\"EntitlementStatus\" value=\"2\"/>" 246 + " </characteristic>" 247 + " <characteristic type=\"APPLICATION\">" 248 + " <parm name=\"AppID\" value=\"ap2004\"/>" 249 + " <parm name=\"EntitlementStatus\" value=\"2\"/>" 250 + " </characteristic>" 251 + " <characteristic type=\"APPLICATION\">" 252 + " <parm name=\"AppID\" value=\"ap2005\"/>" 253 + " <parm name=\"EntitlementStatus\" value=\"2\"/>" 254 + " </characteristic>" 255 + "</wap-provisioningdoc>"; 256 update(rawXml); 257 } 258 } 259