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