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 17 package com.android.server.wifi.entitlement.response; 18 19 import static android.text.format.DateUtils.HOUR_IN_MILLIS; 20 21 import android.text.TextUtils; 22 import android.util.Log; 23 24 import com.android.internal.annotations.VisibleForTesting; 25 import com.android.server.wifi.entitlement.PseudonymInfo; 26 import com.android.server.wifi.entitlement.RequestFactory; 27 28 import org.json.JSONArray; 29 import org.json.JSONException; 30 import org.json.JSONObject; 31 32 import java.util.Optional; 33 34 35 /** The response of get IMSI pseudonym request */ 36 public class GetImsiPseudonymResponse extends Response { 37 private static final String TAG = "WifiEntitlement(GetImsiPseudonymResponse)"; 38 @VisibleForTesting 39 static final String JSON_KEY_IMSI_PSEUDONYM = "imsi-pseudonym"; 40 @VisibleForTesting 41 public static final String JSON_KEY_REFRESH_INTERVAL = "refresh-interval"; 42 43 // Refer to https://www.rfc-editor.org/rfc/rfc3748#section-3.1 44 private static final int EAP_MTU = 1020; 45 private int mGetImsiPseudonymResponseCode; 46 private int mRefreshInterval; 47 private String mImsiPseudonym; 48 GetImsiPseudonymResponse(String responseBody)49 public GetImsiPseudonymResponse(String responseBody) { 50 if (TextUtils.isEmpty(responseBody)) { 51 Log.e(TAG, "Error! Empty responseBody!"); 52 return; 53 } 54 try { 55 JSONArray array = new JSONArray(responseBody); 56 for (int i = 0; i < array.length(); i++) { 57 JSONObject object = array.optJSONObject(i); 58 if (object == null) { 59 continue; 60 } 61 int id = object.optInt(JSON_KEY_MESSAGE_ID, -1); 62 switch (id) { 63 case RequestFactory.MESSAGE_ID_3GPP_AUTHENTICATION: 64 parse3gppAuthentication(object); 65 break; 66 case RequestFactory.MESSAGE_ID_GET_IMSI_PSEUDONYM: 67 parseGetImsiPseudonym(object); 68 break; 69 default: 70 Log.e(TAG, "Unexpected Message ID >> " + id); 71 } 72 } 73 } catch (JSONException e) { 74 Log.e(TAG, "ERROR! not a valid JSONArray String![" + responseBody + "]", e); 75 } 76 } 77 parseGetImsiPseudonym(JSONObject object)78 private void parseGetImsiPseudonym(JSONObject object) { 79 mGetImsiPseudonymResponseCode = object.optInt(JSON_KEY_RESPONSE_CODE, -1); 80 mImsiPseudonym = object.optString(JSON_KEY_IMSI_PSEUDONYM, null); 81 mRefreshInterval = object.optInt(JSON_KEY_REFRESH_INTERVAL, -1); 82 } 83 84 /** Returns {@code PseudonymInfo} with server returned information. */ toPseudonymInfo(String imsi)85 public Optional<PseudonymInfo> toPseudonymInfo(String imsi) { 86 PseudonymInfo pseudonymInfo = null; 87 boolean success = 88 (mAuthResponseCode == RESPONSE_CODE_REQUEST_SUCCESSFUL) 89 && (mGetImsiPseudonymResponseCode == RESPONSE_CODE_REQUEST_SUCCESSFUL); 90 if (success && (mImsiPseudonym != null) && (mImsiPseudonym.length() <= EAP_MTU)) { 91 if (mRefreshInterval <= 0) { 92 pseudonymInfo = new PseudonymInfo(mImsiPseudonym, imsi); 93 } else { 94 pseudonymInfo = new PseudonymInfo(mImsiPseudonym, imsi, 95 mRefreshInterval * HOUR_IN_MILLIS); 96 } 97 } 98 return Optional.ofNullable(pseudonymInfo); 99 } 100 101 /** Returns AKA token. */ getAkaToken()102 public String getAkaToken() { 103 return mAkaToken; 104 } 105 getGetImsiPseudonymResponseCode()106 public int getGetImsiPseudonymResponseCode() { 107 return mGetImsiPseudonymResponseCode; 108 } 109 } 110 111