14035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly/*
24035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly * Copyright (C) 2012 The Android Open Source Project
34035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly *
44035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly * Licensed under the Apache License, Version 2.0 (the "License");
54035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly * you may not use this file except in compliance with the License.
64035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly * You may obtain a copy of the License at
74035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly *
84035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly *      http://www.apache.org/licenses/LICENSE-2.0
94035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly *
104035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly * Unless required by applicable law or agreed to in writing, software
114035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly * distributed under the License is distributed on an "AS IS" BASIS,
124035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly * See the License for the specific language governing permissions and
144035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly * limitations under the License.
154035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly */
164035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly
174035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly
184035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pellypackage com.android.server.location;
194035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly
204035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pellyimport android.content.Context;
214035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pellyimport android.database.ContentObserver;
224035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pellyimport android.os.Handler;
2383762d22c9bde92d412cf5a263a228d705606721Victoria Leaseimport android.os.UserHandle;
244035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pellyimport android.provider.Settings;
254035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pellyimport android.util.Log;
264035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pellyimport android.util.Slog;
274035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly
284035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pellyimport com.android.server.LocationManagerService;
294035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly
304035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pellyimport java.io.PrintWriter;
314035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pellyimport java.util.ArrayList;
324035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pellyimport java.util.Arrays;
334035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly
344035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly/**
354035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly * Allows applications to be blacklisted from location updates at run-time.
364035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly *
374035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly * This is a silent blacklist. Applications can still call Location Manager
384035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly * API's, but they just won't receive any locations.
394035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly */
404035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pellypublic final class LocationBlacklist extends ContentObserver {
414035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly    private static final String TAG = "LocationBlacklist";
424035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly    private static final boolean D = LocationManagerService.D;
434035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly    private static final String BLACKLIST_CONFIG_NAME = "locationPackagePrefixBlacklist";
444035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly    private static final String WHITELIST_CONFIG_NAME = "locationPackagePrefixWhitelist";
454035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly
464035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly    private final Context mContext;
474035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly    private final Object mLock = new Object();
484035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly
494035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly    // all fields below synchronized on mLock
504035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly    private String[] mWhitelist = new String[0];
514035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly    private String[] mBlacklist = new String[0];
5283762d22c9bde92d412cf5a263a228d705606721Victoria Lease
5398404fdc0b73e6563c19b863aa5ab605e092de29Xiaohui Chen    private int mCurrentUserId = UserHandle.USER_SYSTEM;
544035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly
554035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly    public LocationBlacklist(Context context, Handler handler) {
564035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly        super(handler);
574035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly        mContext = context;
584035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly    }
594035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly
604035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly    public void init() {
614035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly        mContext.getContentResolver().registerContentObserver(Settings.Secure.getUriFor(
6283762d22c9bde92d412cf5a263a228d705606721Victoria Lease                BLACKLIST_CONFIG_NAME), false, this, UserHandle.USER_ALL);
634035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly//        mContext.getContentResolver().registerContentObserver(Settings.Secure.getUriFor(
6483762d22c9bde92d412cf5a263a228d705606721Victoria Lease//                WHITELIST_CONFIG_NAME), false, this, UserHandle.USER_ALL);
654035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly        reloadBlacklist();
664035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly    }
674035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly
6883762d22c9bde92d412cf5a263a228d705606721Victoria Lease    private void reloadBlacklistLocked() {
6983762d22c9bde92d412cf5a263a228d705606721Victoria Lease        mWhitelist = getStringArrayLocked(WHITELIST_CONFIG_NAME);
705e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn        if (D) Slog.d(TAG, "whitelist: " + Arrays.toString(mWhitelist));
7183762d22c9bde92d412cf5a263a228d705606721Victoria Lease        mBlacklist = getStringArrayLocked(BLACKLIST_CONFIG_NAME);
725e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn        if (D) Slog.d(TAG, "blacklist: " + Arrays.toString(mBlacklist));
7383762d22c9bde92d412cf5a263a228d705606721Victoria Lease    }
7483762d22c9bde92d412cf5a263a228d705606721Victoria Lease
754035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly    private void reloadBlacklist() {
764035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly        synchronized (mLock) {
7783762d22c9bde92d412cf5a263a228d705606721Victoria Lease            reloadBlacklistLocked();
784035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly        }
794035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly    }
804035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly
814035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly    /**
824035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly     * Return true if in blacklist
834035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly     * (package name matches blacklist, and does not match whitelist)
844035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly     */
854035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly    public boolean isBlacklisted(String packageName) {
864035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly        synchronized (mLock) {
874035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly            for (String black : mBlacklist) {
884035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly                if (packageName.startsWith(black)) {
894035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly                    if (inWhitelist(packageName)) {
904035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly                        continue;
914035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly                    } else {
924035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly                        if (D) Log.d(TAG, "dropping location (blacklisted): "
934035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly                                + packageName + " matches " + black);
944035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly                        return true;
954035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly                    }
964035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly                }
974035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly            }
984035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly        }
994035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly        return false;
1004035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly    }
1014035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly
1024035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly    /**
1034035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly     * Return true if any of packages are in whitelist
1044035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly     */
1054035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly    private boolean inWhitelist(String pkg) {
1064035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly        synchronized (mLock) {
1074035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly            for (String white : mWhitelist) {
1084035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly                if (pkg.startsWith(white)) return true;
1094035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly            }
1104035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly        }
1114035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly        return false;
1124035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly    }
1134035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly
1144035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly    @Override
1154035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly    public void onChange(boolean selfChange) {
1164035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly        reloadBlacklist();
1174035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly    }
1184035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly
11983762d22c9bde92d412cf5a263a228d705606721Victoria Lease    public void switchUser(int userId) {
12083762d22c9bde92d412cf5a263a228d705606721Victoria Lease        synchronized(mLock) {
12183762d22c9bde92d412cf5a263a228d705606721Victoria Lease            mCurrentUserId = userId;
12283762d22c9bde92d412cf5a263a228d705606721Victoria Lease            reloadBlacklistLocked();
12383762d22c9bde92d412cf5a263a228d705606721Victoria Lease        }
12483762d22c9bde92d412cf5a263a228d705606721Victoria Lease    }
12583762d22c9bde92d412cf5a263a228d705606721Victoria Lease
12683762d22c9bde92d412cf5a263a228d705606721Victoria Lease    private String[] getStringArrayLocked(String key) {
12783762d22c9bde92d412cf5a263a228d705606721Victoria Lease        String flatString;
12883762d22c9bde92d412cf5a263a228d705606721Victoria Lease        synchronized(mLock) {
12983762d22c9bde92d412cf5a263a228d705606721Victoria Lease            flatString = Settings.Secure.getStringForUser(mContext.getContentResolver(), key,
13083762d22c9bde92d412cf5a263a228d705606721Victoria Lease                    mCurrentUserId);
13183762d22c9bde92d412cf5a263a228d705606721Victoria Lease        }
1324035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly        if (flatString == null) {
1334035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly            return new String[0];
1344035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly        }
1354035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly        String[] splitStrings = flatString.split(",");
1364035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly        ArrayList<String> result = new ArrayList<String>();
1374035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly        for (String pkg : splitStrings) {
1384035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly            pkg = pkg.trim();
1394035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly            if (pkg.isEmpty()) {
1404035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly                continue;
1414035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly            }
1424035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly            result.add(pkg);
1434035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly        }
1444035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly        return result.toArray(new String[result.size()]);
1454035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly    }
1464035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly
1474035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly    public void dump(PrintWriter pw) {
1484035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly        pw.println("mWhitelist=" + Arrays.toString(mWhitelist) + " mBlacklist=" +
1494035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly                Arrays.toString(mBlacklist));
1504035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly    }
1514035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly}
152