171a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvistpackage com.android.server.wifi.anqp;
271a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist
37ec7de9f415179e38a39e7b1be917ba77e3b68ebJan Nordqvistimport java.net.ProtocolException;
471a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvistimport java.nio.ByteBuffer;
571a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvistimport java.util.ArrayList;
607f11f6f2ee7ec17cb08180035dfb5002aaaf5dfJan Nordqvistimport java.util.Iterator;
771a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvistimport java.util.List;
871a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist
971a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvistimport static com.android.server.wifi.anqp.Constants.BYTE_MASK;
1071a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist
1107f11f6f2ee7ec17cb08180035dfb5002aaaf5dfJan Nordqvistpublic class CellularNetwork implements Iterable<String> {
1271a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist    private static final int PLMNListType = 0;
1371a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist
1407f11f6f2ee7ec17cb08180035dfb5002aaaf5dfJan Nordqvist    private final List<String> mMccMnc;
1571a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist
167ec7de9f415179e38a39e7b1be917ba77e3b68ebJan Nordqvist    private CellularNetwork(int plmnCount, ByteBuffer payload) throws ProtocolException {
177ec7de9f415179e38a39e7b1be917ba77e3b68ebJan Nordqvist        mMccMnc = new ArrayList<>(plmnCount);
1871a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist
1971a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        while (plmnCount > 0) {
207ec7de9f415179e38a39e7b1be917ba77e3b68ebJan Nordqvist            if (payload.remaining() < 3) {
217ec7de9f415179e38a39e7b1be917ba77e3b68ebJan Nordqvist                throw new ProtocolException("Truncated PLMN info");
227ec7de9f415179e38a39e7b1be917ba77e3b68ebJan Nordqvist            }
2371a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist            byte[] plmn = new byte[3];
2471a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist            payload.get(plmn);
2571a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist
267ec7de9f415179e38a39e7b1be917ba77e3b68ebJan Nordqvist            int mcc = ((plmn[0] << 8) & 0xf00) |
277ec7de9f415179e38a39e7b1be917ba77e3b68ebJan Nordqvist                    (plmn[0] & 0x0f0) |
287ec7de9f415179e38a39e7b1be917ba77e3b68ebJan Nordqvist                    (plmn[1] & 0x00f);
2971a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist
307ec7de9f415179e38a39e7b1be917ba77e3b68ebJan Nordqvist            int mnc = ((plmn[2] << 4) & 0xf0) |
317ec7de9f415179e38a39e7b1be917ba77e3b68ebJan Nordqvist                    ((plmn[2] >> 4) & 0x0f);
3271a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist
337ec7de9f415179e38a39e7b1be917ba77e3b68ebJan Nordqvist            int n2 = (plmn[1] >> 4) & 0x0f;
3407f11f6f2ee7ec17cb08180035dfb5002aaaf5dfJan Nordqvist            String mccMnc = n2 != 0xf ?
3507f11f6f2ee7ec17cb08180035dfb5002aaaf5dfJan Nordqvist                    String.format("%03x%03x", mcc, (mnc << 4) | n2) :
3607f11f6f2ee7ec17cb08180035dfb5002aaaf5dfJan Nordqvist                    String.format("%03x%02x", mcc, mnc);
3771a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist
3807f11f6f2ee7ec17cb08180035dfb5002aaaf5dfJan Nordqvist            mMccMnc.add(mccMnc);
397ec7de9f415179e38a39e7b1be917ba77e3b68ebJan Nordqvist            plmnCount--;
4071a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        }
4171a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist    }
4271a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist
4307f11f6f2ee7ec17cb08180035dfb5002aaaf5dfJan Nordqvist    public static CellularNetwork buildCellularNetwork(ByteBuffer payload)
4407f11f6f2ee7ec17cb08180035dfb5002aaaf5dfJan Nordqvist            throws ProtocolException {
4571a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        int iei = payload.get() & BYTE_MASK;
4671a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        int plmnLen = payload.get() & 0x7f;
4771a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist
4871a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        if (iei != PLMNListType) {
4971a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist            payload.position(payload.position() + plmnLen);
5071a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist            return null;
5171a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        }
5271a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist
5371a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        int plmnCount = payload.get() & BYTE_MASK;
5471a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        return new CellularNetwork(plmnCount, payload);
5571a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist    }
5671a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist
5707f11f6f2ee7ec17cb08180035dfb5002aaaf5dfJan Nordqvist    @Override
5807f11f6f2ee7ec17cb08180035dfb5002aaaf5dfJan Nordqvist    public Iterator<String> iterator() {
5907f11f6f2ee7ec17cb08180035dfb5002aaaf5dfJan Nordqvist        return mMccMnc.iterator();
6071a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist    }
6171a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist
6271a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist    @Override
6371a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist    public String toString() {
6471a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        StringBuilder sb = new StringBuilder("PLMN:");
6507f11f6f2ee7ec17cb08180035dfb5002aaaf5dfJan Nordqvist        for (String mccMnc : mMccMnc) {
6607f11f6f2ee7ec17cb08180035dfb5002aaaf5dfJan Nordqvist            sb.append(' ').append(mccMnc);
6771a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        }
6871a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        return sb.toString();
6971a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist    }
7071a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist}
71