1 /*
2  * Copyright (C) 2014 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;
18 
19 import android.content.ContentResolver;
20 import android.content.Context;
21 import android.database.Cursor;
22 import android.util.Log;
23 
24 import com.android.internal.telephony.HbpcdLookup.ArbitraryMccSidMatch;
25 import com.android.internal.telephony.HbpcdLookup.MccIdd;
26 import com.android.internal.telephony.HbpcdLookup.MccLookup;
27 import com.android.internal.telephony.HbpcdLookup.MccSidConflicts;
28 import com.android.internal.telephony.HbpcdLookup.MccSidRange;
29 
30 public final class HbpcdUtils {
31     private static final String LOG_TAG = "HbpcdUtils";
32     private static final boolean DBG = false;
33     private ContentResolver resolver = null;
34 
HbpcdUtils(Context context)35     public HbpcdUtils(Context context) {
36         resolver = context.getContentResolver();
37     }
38 
39     /**
40      *  Resolves the unknown MCC with SID and Timezone information.
41     */
getMcc(int sid, int tz, int DSTflag, boolean isNitzTimeZone)42     public int getMcc(int sid, int tz, int DSTflag, boolean isNitzTimeZone) {
43         int tmpMcc = 0;
44 
45         // check if SID exists in arbitrary_mcc_sid_match table.
46         // these SIDs are assigned to more than 1 operators, but they are known to
47         // be used by a specific operator, other operators having the same SID are
48         // not using it currently, if that SID is in this table, we don't need to
49         // check other tables.
50         String projection2[] = {ArbitraryMccSidMatch.MCC};
51         Cursor c2 = resolver.query(ArbitraryMccSidMatch.CONTENT_URI, projection2,
52                             ArbitraryMccSidMatch.SID + "=" + sid, null, null);
53 
54         if (c2 != null) {
55             int c2Counter = c2.getCount();
56             if (DBG) {
57                 Log.d(LOG_TAG, "Query unresolved arbitrary table, entries are " + c2Counter);
58             }
59             if (c2Counter == 1) {
60                 if (DBG) {
61                     Log.d(LOG_TAG, "Query Unresolved arbitrary returned the cursor " + c2);
62                 }
63                 c2.moveToFirst();
64                 tmpMcc = c2.getInt(0);
65                 if (DBG) {
66                     Log.d(LOG_TAG, "MCC found in arbitrary_mcc_sid_match: " + tmpMcc);
67                 }
68                 c2.close();
69                 return tmpMcc;
70             }
71             c2.close();
72         }
73 
74         // Then check if SID exists in mcc_sid_conflict table.
75         // and use the timezone in mcc_lookup table to check which MCC matches.
76         String projection3[] = {MccSidConflicts.MCC};
77         Cursor c3 = resolver.query(MccSidConflicts.CONTENT_URI, projection3,
78                 MccSidConflicts.SID_CONFLICT + "=" + sid + " and (((" +
79                 MccLookup.GMT_OFFSET_LOW + "<=" + tz + ") and (" + tz + "<=" +
80                 MccLookup.GMT_OFFSET_HIGH + ") and (" + "0=" + DSTflag + ")) or ((" +
81                 MccLookup.GMT_DST_LOW + "<=" + tz + ") and (" + tz + "<=" +
82                 MccLookup.GMT_DST_HIGH + ") and (" + "1=" + DSTflag + ")))",
83                         null, null);
84         if (c3 != null) {
85             int c3Counter = c3.getCount();
86             if (c3Counter > 0) {
87                 if (c3Counter > 1) {
88                     Log.w(LOG_TAG, "something wrong, get more results for 1 conflict SID: " + c3);
89                 }
90                 if (DBG) Log.d(LOG_TAG, "Query conflict sid returned the cursor " + c3);
91                 c3.moveToFirst();
92                 tmpMcc = c3.getInt(0);
93                 if (DBG) {
94                     Log.d(LOG_TAG, "MCC found in mcc_lookup_table. Return tmpMcc = " + tmpMcc);
95                 }
96                 if (!isNitzTimeZone) {
97                     // time zone is not accurate, it may get wrong mcc, ignore it.
98                     if (DBG) {
99                         Log.d(LOG_TAG, "time zone is not accurate, mcc may be " + tmpMcc);
100                     }
101                     tmpMcc = 0;
102                 }
103                 c3.close();
104                 return tmpMcc;
105             } else {
106                 c3.close();
107             }
108         }
109 
110         // if there is no conflict, then check if SID is in mcc_sid_range.
111         String projection5[] = {MccSidRange.MCC};
112         Cursor c5 = resolver.query(MccSidRange.CONTENT_URI, projection5,
113                 MccSidRange.RANGE_LOW + "<=" + sid + " and " +
114                 MccSidRange.RANGE_HIGH + ">=" + sid,
115                 null, null);
116         if (c5 != null) {
117             if (c5.getCount() > 0) {
118                 if (DBG) Log.d(LOG_TAG, "Query Range returned the cursor " + c5);
119                 c5.moveToFirst();
120                 tmpMcc = c5.getInt(0);
121                 if (DBG) Log.d(LOG_TAG, "SID found in mcc_sid_range. Return tmpMcc = " + tmpMcc);
122                 c5.close();
123                 return tmpMcc;
124             }
125             c5.close();
126         }
127         if (DBG) Log.d(LOG_TAG, "SID NOT found in mcc_sid_range.");
128 
129         if (DBG) Log.d(LOG_TAG, "Exit getMccByOtherFactors. Return tmpMcc =  " + tmpMcc);
130         // If unknown MCC still could not be resolved,
131         return tmpMcc;
132     }
133 
134     /**
135      *  Gets country information with given MCC.
136     */
getIddByMcc(int mcc)137     public String getIddByMcc(int mcc) {
138         if (DBG) Log.d(LOG_TAG, "Enter getHbpcdInfoByMCC.");
139         String idd = "";
140 
141         Cursor c = null;
142 
143         String projection[] = {MccIdd.IDD};
144         Cursor cur = resolver.query(MccIdd.CONTENT_URI, projection,
145                 MccIdd.MCC + "=" + mcc, null, null);
146         if (cur != null) {
147             if (cur.getCount() > 0) {
148                 if (DBG) Log.d(LOG_TAG, "Query Idd returned the cursor " + cur);
149                 // TODO: for those country having more than 1 IDDs, need more information
150                 // to decide which IDD would be used. currently just use the first 1.
151                 cur.moveToFirst();
152                 idd = cur.getString(0);
153                 if (DBG) Log.d(LOG_TAG, "IDD = " + idd);
154 
155             }
156             cur.close();
157         }
158         if (c != null) c.close();
159 
160         if (DBG) Log.d(LOG_TAG, "Exit getHbpcdInfoByMCC.");
161         return idd;
162     }
163 }
164