1 package com.google.android.iwlan.epdg; 2 3 import android.support.annotation.NonNull; 4 import android.telephony.data.NetworkSliceInfo; 5 import android.util.Log; 6 7 import java.util.Arrays; 8 import java.util.List; 9 10 public class NetworkSliceSelectionAssistanceInformation { 11 private static final String TAG = 12 NetworkSliceSelectionAssistanceInformation.class.getSimpleName(); 13 static final List<Integer> VALID_LENGTHS = Arrays.asList(1, 2, 4, 5, 8); 14 getSliceInfo(byte[] snssai)15 public static NetworkSliceInfo getSliceInfo(byte[] snssai) { 16 if (snssai == null) { 17 return null; 18 } 19 /** 20 * From 3GPP TS 24.501 Section 9.11.2.8, Content structure of the Value of S-NSSAI 21 * 22 * <p>Slice Service Type - 1 byte 23 * Slice Differentiator - 3 bytes 24 * Mapped HPLMN Slice Service Type - 1 byte 25 * Mapped HPLMN Slice Differentiator - 3 bytes 26 * 27 * <p>Depending on the value of the length field the following S-NSSAI contents are 28 * included: 29 * Bits 8 7 6 5 4 3 2 1 30 * 0 0 0 0 0 0 0 1 SST 31 * 0 0 0 0 0 0 1 0 SST and mapped HPLMN SST 32 * 0 0 0 0 0 1 0 0 SST and SD 33 * 0 0 0 0 0 1 0 1 SST, SD and mapped HPLMN SST 34 * 0 0 0 0 1 0 0 0 SST, SD, mapped HPLMN SST and mapped HPLMN SD 35 * All other values are reserved. 36 */ 37 NetworkSliceInfo.Builder siBuilder = new NetworkSliceInfo.Builder(); 38 int len = snssai.length; 39 // validity checks. See TS 24.501 Section 9.11.2.8 40 // length should be valid 41 if (!VALID_LENGTHS.contains(len)) { 42 Log.d(TAG, "Invalid S-NSSAI length : " + snssai.length); 43 return null; 44 } 45 46 switch (len) { 47 case 1: // get SST 48 siBuilder.setSliceServiceType(getSST(snssai, 0)); 49 break; 50 case 2: // get SST and mapped SST 51 siBuilder.setSliceServiceType(getSST(snssai, 0)); 52 siBuilder.setMappedHplmnSliceServiceType(getSST(snssai, 1)); 53 break; 54 case 4: // get SST and SD 55 siBuilder.setSliceServiceType(getSST(snssai, 0)); 56 siBuilder.setSliceDifferentiator(getSD(snssai, 1)); 57 break; 58 case 5: // get SST, SD and mapped SST 59 siBuilder.setSliceServiceType(getSST(snssai, 0)); 60 siBuilder.setSliceDifferentiator(getSD(snssai, 1)); 61 siBuilder.setMappedHplmnSliceServiceType(getSST(snssai, 4)); 62 break; 63 case 8: // get SST, SD, mapped SST, mapped SD 64 siBuilder.setSliceServiceType(getSST(snssai, 0)); 65 siBuilder.setSliceDifferentiator(getSD(snssai, 1)); 66 siBuilder.setMappedHplmnSliceServiceType(getSST(snssai, 4)); 67 siBuilder.setMappedHplmnSliceDifferentiator(getSD(snssai, 5)); 68 break; 69 } 70 71 return siBuilder.build(); 72 } 73 getSST(@onNull byte[] snssai, int offset)74 private static int getSST(@NonNull byte[] snssai, int offset) { 75 if (offset < 0 || snssai.length < offset + 1) { 76 return NetworkSliceInfo.SLICE_SERVICE_TYPE_NONE; 77 } 78 /** 79 * From 3GPP TS 23.003: Values 0 to 127 belong to the standardized SST range and they are 80 * defined in 3GPP TS 23.501. Values 128 to 255 belong to the Operator-specific range 81 */ 82 return Byte.toUnsignedInt(snssai[offset]); 83 } 84 getSD(byte[] snssai, int offset)85 private static int getSD(byte[] snssai, int offset) { 86 int sliceDescriptor = NetworkSliceInfo.SLICE_SERVICE_TYPE_NONE; 87 /* 88 * Slice Descriptor is 3 bytes long 89 * The SD field has a reserved value "no SD value associated with the SST" 90 * defined as hexadecimal FFFFFF 91 */ 92 if (offset >= 0 && snssai.length >= offset + 3) { 93 int sd = 0; 94 sd = 95 (sd | snssai[offset + 2]) 96 | ((sd | snssai[offset + 1]) << 8) 97 | ((sd | snssai[offset]) << 16); 98 if (sd != 0xFFFFFF) { 99 sliceDescriptor = sd; 100 } 101 } 102 return sliceDescriptor; 103 } 104 } 105