1 package com.android.server.location;
2 
3 import android.content.ContentResolver;
4 import android.content.Context;
5 import android.database.ContentObserver;
6 import android.os.Handler;
7 import android.os.Looper;
8 import android.os.UserHandle;
9 import android.provider.Settings;
10 import android.util.Log;
11 
12 import com.android.internal.annotations.VisibleForTesting;
13 
14 import java.util.ArrayList;
15 import java.util.List;
16 
17 /**
18  * Detects blacklist change and updates the blacklist.
19  */
20 class GnssSatelliteBlacklistHelper {
21 
22     private static final String TAG = "GnssBlacklistHelper";
23     private static final String BLACKLIST_DELIMITER = ",";
24 
25     private final Context mContext;
26     private final GnssSatelliteBlacklistCallback mCallback;
27 
28     interface GnssSatelliteBlacklistCallback {
onUpdateSatelliteBlacklist(int[] constellations, int[] svids)29         void onUpdateSatelliteBlacklist(int[] constellations, int[] svids);
30     }
31 
GnssSatelliteBlacklistHelper(Context context, Looper looper, GnssSatelliteBlacklistCallback callback)32     GnssSatelliteBlacklistHelper(Context context, Looper looper,
33             GnssSatelliteBlacklistCallback callback) {
34         mContext = context;
35         mCallback = callback;
36         ContentObserver contentObserver = new ContentObserver(new Handler(looper)) {
37             @Override
38             public void onChange(boolean selfChange) {
39                 updateSatelliteBlacklist();
40             }
41         };
42         mContext.getContentResolver().registerContentObserver(
43                 Settings.Global.getUriFor(
44                         Settings.Global.GNSS_SATELLITE_BLACKLIST),
45                 true,
46                 contentObserver, UserHandle.USER_ALL);
47     }
48 
updateSatelliteBlacklist()49     void updateSatelliteBlacklist() {
50         ContentResolver resolver = mContext.getContentResolver();
51         String blacklist = Settings.Global.getString(
52                 resolver,
53                 Settings.Global.GNSS_SATELLITE_BLACKLIST);
54         if (blacklist == null) {
55             blacklist = "";
56         }
57         Log.i(TAG, String.format("Update GNSS satellite blacklist: %s", blacklist));
58 
59         List<Integer> blacklistValues;
60         try {
61             blacklistValues = parseSatelliteBlacklist(blacklist);
62         } catch (NumberFormatException e) {
63             Log.e(TAG, "Exception thrown when parsing blacklist string.", e);
64             return;
65         }
66 
67         if (blacklistValues.size() % 2 != 0) {
68             Log.e(TAG, "blacklist string has odd number of values."
69                     + "Aborting updateSatelliteBlacklist");
70             return;
71         }
72 
73         int length = blacklistValues.size() / 2;
74         int[] constellations = new int[length];
75         int[] svids = new int[length];
76         for (int i = 0; i < length; i++) {
77             constellations[i] = blacklistValues.get(i * 2);
78             svids[i] = blacklistValues.get(i * 2 + 1);
79         }
80         mCallback.onUpdateSatelliteBlacklist(constellations, svids);
81     }
82 
83     @VisibleForTesting
parseSatelliteBlacklist(String blacklist)84     static List<Integer> parseSatelliteBlacklist(String blacklist) throws NumberFormatException {
85         String[] strings = blacklist.split(BLACKLIST_DELIMITER);
86         List<Integer> parsed = new ArrayList<>(strings.length);
87         for (String string : strings) {
88             string = string.trim();
89             if (!"".equals(string)) {
90                 int value = Integer.parseInt(string);
91                 if (value < 0) {
92                     throw new NumberFormatException("Negative value is invalid.");
93                 }
94                 parsed.add(value);
95             }
96         }
97         return parsed;
98     }
99 }
100