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.internal.telephony.satellite; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.content.Context; 22 import android.util.ArraySet; 23 import android.util.Log; 24 25 import com.android.internal.annotations.VisibleForTesting; 26 import com.android.internal.telephony.satellite.nano.SatelliteConfigData; 27 28 import java.io.ByteArrayInputStream; 29 import java.io.File; 30 import java.io.IOException; 31 import java.io.InputStream; 32 import java.nio.file.Files; 33 import java.nio.file.Path; 34 import java.nio.file.StandardCopyOption; 35 import java.util.ArrayList; 36 import java.util.HashMap; 37 import java.util.HashSet; 38 import java.util.List; 39 import java.util.Map; 40 import java.util.Set; 41 42 /** 43 * SatelliteConfig is utility class for satellite. 44 * It is obtained through the getConfig() at the SatelliteConfigParser. 45 */ 46 public class SatelliteConfig { 47 48 private static final String TAG = "SatelliteConfig"; 49 private static final String SATELLITE_DIR_NAME = "satellite"; 50 private static final String S2_CELL_FILE_NAME = "s2_cell_file"; 51 private int mVersion; 52 private Map<Integer, Map<String, Set<Integer>>> mSupportedServicesPerCarrier; 53 private List<String> mSatelliteRegionCountryCodes; 54 private Boolean mIsSatelliteRegionAllowed; 55 private File mSatS2File; 56 private SatelliteConfigData.SatelliteConfigProto mConfigData; 57 SatelliteConfig(SatelliteConfigData.SatelliteConfigProto configData)58 public SatelliteConfig(SatelliteConfigData.SatelliteConfigProto configData) { 59 mConfigData = configData; 60 mVersion = mConfigData.version; 61 mSupportedServicesPerCarrier = getCarrierSupportedSatelliteServices(); 62 mSatelliteRegionCountryCodes = List.of( 63 mConfigData.deviceSatelliteRegion.countryCodes); 64 mIsSatelliteRegionAllowed = mConfigData.deviceSatelliteRegion.isAllowed; 65 mSatS2File = null; 66 67 Log.d(TAG, "mVersion:" + mVersion + " | " 68 + "mSupportedServicesPerCarrier:" + mSupportedServicesPerCarrier + " | " 69 + "mSatelliteRegionCountryCodes:" 70 + String.join(",", mSatelliteRegionCountryCodes) + " | " 71 + "mIsSatelliteRegionAllowed:" + mIsSatelliteRegionAllowed + " | " 72 + " | s2CellFile size:" + mConfigData.deviceSatelliteRegion.s2CellFile.length); 73 } 74 75 /** 76 * @return a Map data with carrier_id, plmns and allowed_services. 77 */ getCarrierSupportedSatelliteServices()78 private Map<Integer, Map<String, Set<Integer>>> getCarrierSupportedSatelliteServices() { 79 SatelliteConfigData.CarrierSupportedSatelliteServicesProto[] satelliteServices = 80 mConfigData.carrierSupportedSatelliteServices; 81 Map<Integer, Map<String, Set<Integer>>> carrierToServicesMap = new HashMap<>(); 82 for (SatelliteConfigData.CarrierSupportedSatelliteServicesProto carrierProto : 83 satelliteServices) { 84 SatelliteConfigData.SatelliteProviderCapabilityProto[] satelliteCapabilities = 85 carrierProto.supportedSatelliteProviderCapabilities; 86 Map<String, Set<Integer>> satelliteCapabilityMap = new HashMap<>(); 87 for (SatelliteConfigData.SatelliteProviderCapabilityProto capabilityProto : 88 satelliteCapabilities) { 89 String carrierPlmn = capabilityProto.carrierPlmn; 90 Set<Integer> allowedServices = new HashSet<>(); 91 for (int service : capabilityProto.allowedServices) { 92 allowedServices.add(service); 93 } 94 satelliteCapabilityMap.put(carrierPlmn, allowedServices); 95 } 96 carrierToServicesMap.put(carrierProto.carrierId, satelliteCapabilityMap); 97 } 98 return carrierToServicesMap; 99 } 100 101 /** 102 * Get satellite plmns for carrier 103 * 104 * @param carrierId the carrier identifier. 105 * @return Plmns corresponding to carrier identifier. 106 */ 107 @NonNull getAllSatellitePlmnsForCarrier(int carrierId)108 public List<String> getAllSatellitePlmnsForCarrier(int carrierId) { 109 if (mSupportedServicesPerCarrier != null) { 110 Map<String, Set<Integer>> satelliteCapabilitiesMap = mSupportedServicesPerCarrier.get( 111 carrierId); 112 if (satelliteCapabilitiesMap != null) { 113 return new ArrayList<>(satelliteCapabilitiesMap.keySet()); 114 } 115 } 116 Log.d(TAG, "getAllSatellitePlmnsForCarrier : mConfigData is null or no config data"); 117 return new ArrayList<>(); 118 } 119 120 /** 121 * Get supported satellite services of all providers for a carrier. 122 * The format of the return value - Key: PLMN, Value: Set of supported satellite services. 123 * 124 * @param carrierId the carrier identifier. 125 * @return all supported satellite services for a carrier 126 */ 127 @NonNull getSupportedSatelliteServices(int carrierId)128 public Map<String, Set<Integer>> getSupportedSatelliteServices(int carrierId) { 129 if (mSupportedServicesPerCarrier != null) { 130 Map<String, Set<Integer>> satelliteCapaMap = 131 mSupportedServicesPerCarrier.get(carrierId); 132 if (satelliteCapaMap != null) { 133 return satelliteCapaMap; 134 } else { 135 Log.d(TAG, "No supported services found for carrier=" + carrierId); 136 } 137 } else { 138 Log.d(TAG, "mSupportedServicesPerCarrier is null"); 139 } 140 return new HashMap<>(); 141 } 142 143 /** 144 * Get carrier identifier set for the satellite 145 * 146 * @return carrier identifier set from the config data. 147 */ 148 @NonNull getAllSatelliteCarrierIds()149 public Set<Integer> getAllSatelliteCarrierIds() { 150 if (mSupportedServicesPerCarrier != null) { 151 return new ArraySet<>(mSupportedServicesPerCarrier.keySet()); 152 } 153 return new ArraySet<>(); 154 } 155 156 /** 157 * @return satellite region country codes 158 */ 159 @NonNull getDeviceSatelliteCountryCodes()160 public List<String> getDeviceSatelliteCountryCodes() { 161 if (mSatelliteRegionCountryCodes != null) { 162 return mSatelliteRegionCountryCodes; 163 } 164 Log.d(TAG, "getDeviceSatelliteCountryCodes : mConfigData is null or no config data"); 165 return new ArrayList<>(); 166 } 167 168 /** 169 * @return satellite access allow value, if there is no config data then it returns null. 170 */ 171 @Nullable isSatelliteDataForAllowedRegion()172 public Boolean isSatelliteDataForAllowedRegion() { 173 if (mIsSatelliteRegionAllowed == null) { 174 Log.d(TAG, "getIsSatelliteRegionAllowed : mConfigData is null or no config data"); 175 } 176 return mIsSatelliteRegionAllowed; 177 } 178 179 180 /** 181 * @param context the Context 182 * @return satellite s2_cell_file path 183 */ 184 @Nullable getSatelliteS2CellFile(@ullable Context context)185 public File getSatelliteS2CellFile(@Nullable Context context) { 186 if (context == null) { 187 Log.d(TAG, "getSatelliteS2CellFile : context is null"); 188 return null; 189 } 190 191 if (isFileExist(mSatS2File)) { 192 Log.d(TAG, "File mSatS2File is already exist"); 193 return mSatS2File; 194 } 195 196 if (mConfigData != null && mConfigData.deviceSatelliteRegion != null) { 197 mSatS2File = copySatS2FileToPhoneDirectory( 198 context, mConfigData.deviceSatelliteRegion.s2CellFile); 199 return mSatS2File; 200 } 201 Log.d(TAG, "getSatelliteS2CellFile: " 202 + "mConfigData is null or mConfigData.deviceSatelliteRegion is null"); 203 return null; 204 } 205 206 /** 207 * @param context the Context 208 * @param byteArrayFile byte array type of protobuffer config data 209 * @return the satellite_cell_file path 210 */ 211 @Nullable 212 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) copySatS2FileToPhoneDirectory(@ullable Context context, @Nullable byte[] byteArrayFile)213 public File copySatS2FileToPhoneDirectory(@Nullable Context context, 214 @Nullable byte[] byteArrayFile) { 215 216 if (context == null || byteArrayFile == null) { 217 Log.d(TAG, "copySatS2FileToPhoneDirectory : context or byteArrayFile are null"); 218 return null; 219 } 220 221 File satS2FileDir = context.getDir(SATELLITE_DIR_NAME, Context.MODE_PRIVATE); 222 if (!satS2FileDir.exists()) { 223 satS2FileDir.mkdirs(); 224 } 225 226 Path targetSatS2FilePath = satS2FileDir.toPath().resolve(S2_CELL_FILE_NAME); 227 try { 228 InputStream inputStream = new ByteArrayInputStream(byteArrayFile); 229 if (inputStream == null) { 230 Log.d(TAG, "copySatS2FileToPhoneDirectory: Resource=" + S2_CELL_FILE_NAME 231 + " not found"); 232 } else { 233 Files.copy(inputStream, targetSatS2FilePath, StandardCopyOption.REPLACE_EXISTING); 234 } 235 } catch (IOException ex) { 236 Log.e(TAG, "copySatS2FileToPhoneDirectory: ex=" + ex); 237 } 238 return targetSatS2FilePath.toFile(); 239 } 240 241 /** 242 * @return {@code true} if the SatS2File is already existed and {@code false} otherwise. 243 */ 244 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) isFileExist(@ullable File file)245 public boolean isFileExist(@Nullable File file) { 246 if (file == null) { 247 Log.d(TAG, "isFileExist : file is null"); 248 return false; 249 } 250 return file.exists(); 251 } 252 } 253