Search in sources :

Example 6 with ThreadPolicy

use of android.os.StrictMode.ThreadPolicy in project XPrivacy by M66B.

the class PrivacyService method getSetting.

@Override
public PSetting getSetting(PSetting setting) throws RemoteException {
    long start = System.currentTimeMillis();
    // Translate isolated uid
    setting.uid = getIsolatedUid(setting.uid);
    int userId = Util.getUserId(setting.uid);
    // Special case
    if (Meta.cTypeAccountHash.equals(setting.type))
        try {
            setting.type = Meta.cTypeAccount;
            setting.name = Util.sha1(setting.name);
        } catch (Throwable ex) {
            Util.bug(null, ex);
        }
    // Default result
    PSetting result = new PSetting(setting.uid, setting.type, setting.name, setting.value);
    // Disable strict mode
    ThreadPolicy oldPolicy = StrictMode.getThreadPolicy();
    ThreadPolicy newPolicy = new ThreadPolicy.Builder(oldPolicy).permitDiskReads().permitDiskWrites().build();
    StrictMode.setThreadPolicy(newPolicy);
    try {
        // No permissions enforced
        // Check cache
        CSetting key = new CSetting(setting.uid, setting.type, setting.name);
        synchronized (mSettingCache) {
            if (mSettingCache.containsKey(key)) {
                result.value = mSettingCache.get(key).getValue();
                if (result.value == null)
                    // default value
                    result.value = setting.value;
                return result;
            }
        }
        // No persmissions required
        SQLiteDatabase db = getDb();
        if (db == null)
            return result;
        // Fallback
        if (!PrivacyManager.cSettingMigrated.equals(setting.name) && !getSettingBool(userId, PrivacyManager.cSettingMigrated, false)) {
            if (setting.uid == 0)
                result.value = PrivacyProvider.getSettingFallback(setting.name, null, false);
            if (result.value == null) {
                result.value = PrivacyProvider.getSettingFallback(String.format("%s.%d", setting.name, setting.uid), setting.value, false);
                return result;
            }
        }
        // Precompile statement when needed
        if (stmtGetSetting == null) {
            String sql = "SELECT value FROM " + cTableSetting + " WHERE uid=? AND type=? AND name=?";
            stmtGetSetting = db.compileStatement(sql);
        }
        // Execute statement
        boolean found = false;
        mLock.readLock().lock();
        try {
            db.beginTransaction();
            try {
                try {
                    synchronized (stmtGetSetting) {
                        stmtGetSetting.clearBindings();
                        stmtGetSetting.bindLong(1, setting.uid);
                        stmtGetSetting.bindString(2, setting.type);
                        stmtGetSetting.bindString(3, setting.name);
                        result.value = stmtGetSetting.simpleQueryForString();
                        found = true;
                    }
                } catch (SQLiteDoneException ignored) {
                }
                db.setTransactionSuccessful();
            } finally {
                db.endTransaction();
            }
        } finally {
            mLock.readLock().unlock();
        }
        // Add to cache
        key.setValue(found ? result.value : null);
        synchronized (mSettingCache) {
            if (mSettingCache.containsKey(key))
                mSettingCache.remove(key);
            mSettingCache.put(key, key);
        }
        // Default value
        if (result.value == null)
            result.value = setting.value;
    } catch (SQLiteException ex) {
        notifyException(ex);
    } catch (Throwable ex) {
        Util.bug(null, ex);
    } finally {
        StrictMode.setThreadPolicy(oldPolicy);
    }
    long ms = System.currentTimeMillis() - start;
    Util.log(null, ms < PrivacyManager.cWarnServiceDelayMs ? Log.INFO : Log.WARN, String.format("Get service %s %d ms", setting, ms));
    return result;
}
Also used : SQLiteDatabase(android.database.sqlite.SQLiteDatabase) ThreadPolicy(android.os.StrictMode.ThreadPolicy) SQLiteDoneException(android.database.sqlite.SQLiteDoneException) SQLiteException(android.database.sqlite.SQLiteException) SuppressLint(android.annotation.SuppressLint)

Example 7 with ThreadPolicy

use of android.os.StrictMode.ThreadPolicy in project XPrivacy by M66B.

the class PrivacyService method getRestriction.

@Override
public PRestriction getRestriction(final PRestriction restriction, boolean usage, String secret) throws RemoteException {
    long start = System.currentTimeMillis();
    // Translate isolated uid
    restriction.uid = getIsolatedUid(restriction.uid);
    boolean ccached = false;
    boolean mcached = false;
    int userId = Util.getUserId(restriction.uid);
    final PRestriction mresult = new PRestriction(restriction);
    // Disable strict mode
    ThreadPolicy oldPolicy = StrictMode.getThreadPolicy();
    ThreadPolicy newPolicy = new ThreadPolicy.Builder(oldPolicy).permitDiskReads().permitDiskWrites().build();
    StrictMode.setThreadPolicy(newPolicy);
    try {
        // Sanity checks
        if (restriction.restrictionName == null) {
            Util.log(null, Log.ERROR, "Get invalid restriction " + restriction);
            return mresult;
        }
        if (usage && restriction.methodName == null) {
            Util.log(null, Log.ERROR, "Get invalid restriction " + restriction);
            return mresult;
        }
        // Get meta data
        Hook hook = null;
        if (restriction.methodName != null) {
            hook = PrivacyManager.getHook(restriction.restrictionName, restriction.methodName);
            if (hook == null)
                // Can happen after updating
                Util.log(null, Log.WARN, "Hook not found in service: " + restriction);
            else if (hook.getFrom() != null) {
                String version = getSetting(new PSetting(userId, "", PrivacyManager.cSettingVersion, null)).value;
                if (version != null && new Version(version).compareTo(hook.getFrom()) < 0)
                    if (hook.getReplacedRestriction() == null) {
                        Util.log(null, Log.WARN, "Disabled version=" + version + " from=" + hook.getFrom() + " hook=" + hook);
                        return mresult;
                    } else {
                        restriction.restrictionName = hook.getReplacedRestriction();
                        restriction.methodName = hook.getReplacedMethod();
                        Util.log(null, Log.WARN, "Checking " + restriction + " instead of " + hook);
                    }
            }
        }
        // Process IP address
        if (restriction.extra != null && Meta.cTypeIPAddress.equals(hook.whitelist())) {
            int colon = restriction.extra.lastIndexOf(':');
            String address = (colon >= 0 ? restriction.extra.substring(0, colon) : restriction.extra);
            String port = (colon >= 0 ? restriction.extra.substring(colon) : "");
            int slash = address.indexOf('/');
            if (// IP address
            slash == 0)
                restriction.extra = address.substring(slash + 1) + port;
            else if (// Domain name
            slash > 0)
                restriction.extra = address.substring(0, slash) + port;
        }
        // Check for system component
        if (!PrivacyManager.isApplication(restriction.uid))
            if (!getSettingBool(userId, PrivacyManager.cSettingSystem, false))
                return mresult;
        // Check if restrictions enabled
        if (usage && !getSettingBool(restriction.uid, PrivacyManager.cSettingRestricted, true))
            return mresult;
        // Check if can be restricted
        if (!PrivacyManager.canRestrict(restriction.uid, getXUid(), restriction.restrictionName, restriction.methodName, false))
            mresult.asked = true;
        else {
            // Check cache for method
            CRestriction key = new CRestriction(restriction, restriction.extra);
            synchronized (mRestrictionCache) {
                if (mRestrictionCache.containsKey(key)) {
                    mcached = true;
                    CRestriction cache = mRestrictionCache.get(key);
                    mresult.restricted = cache.restricted;
                    mresult.asked = cache.asked;
                }
            }
            if (!mcached) {
                boolean methodFound = false;
                PRestriction cresult = new PRestriction(restriction.uid, restriction.restrictionName, null);
                // Check cache for category
                CRestriction ckey = new CRestriction(cresult, null);
                synchronized (mRestrictionCache) {
                    if (mRestrictionCache.containsKey(ckey)) {
                        ccached = true;
                        CRestriction crestriction = mRestrictionCache.get(ckey);
                        cresult.restricted = crestriction.restricted;
                        cresult.asked = crestriction.asked;
                        mresult.restricted = cresult.restricted;
                        mresult.asked = cresult.asked;
                    }
                }
                // Get database reference
                SQLiteDatabase db = getDb();
                if (db == null)
                    return mresult;
                // Precompile statement when needed
                if (stmtGetRestriction == null) {
                    String sql = "SELECT restricted FROM " + cTableRestriction + " WHERE uid=? AND restriction=? AND method=?";
                    stmtGetRestriction = db.compileStatement(sql);
                }
                // Execute statement
                mLock.readLock().lock();
                try {
                    db.beginTransaction();
                    try {
                        if (!ccached)
                            try {
                                synchronized (stmtGetRestriction) {
                                    stmtGetRestriction.clearBindings();
                                    stmtGetRestriction.bindLong(1, restriction.uid);
                                    stmtGetRestriction.bindString(2, restriction.restrictionName);
                                    stmtGetRestriction.bindString(3, "");
                                    long state = stmtGetRestriction.simpleQueryForLong();
                                    cresult.restricted = ((state & 1) != 0);
                                    cresult.asked = ((state & 2) != 0);
                                    mresult.restricted = cresult.restricted;
                                    mresult.asked = cresult.asked;
                                }
                            } catch (SQLiteDoneException ignored) {
                            }
                        if (restriction.methodName != null)
                            try {
                                synchronized (stmtGetRestriction) {
                                    stmtGetRestriction.clearBindings();
                                    stmtGetRestriction.bindLong(1, restriction.uid);
                                    stmtGetRestriction.bindString(2, restriction.restrictionName);
                                    stmtGetRestriction.bindString(3, restriction.methodName);
                                    long state = stmtGetRestriction.simpleQueryForLong();
                                    // Method can be excepted
                                    if (mresult.restricted)
                                        mresult.restricted = ((state & 1) == 0);
                                    // Category asked=true takes precedence
                                    if (!mresult.asked)
                                        mresult.asked = ((state & 2) != 0);
                                    methodFound = true;
                                }
                            } catch (SQLiteDoneException ignored) {
                            }
                        db.setTransactionSuccessful();
                    } finally {
                        db.endTransaction();
                    }
                } finally {
                    mLock.readLock().unlock();
                }
                // Default dangerous
                if (!methodFound && hook != null && hook.isDangerous())
                    if (!getSettingBool(userId, PrivacyManager.cSettingDangerous, false)) {
                        if (mresult.restricted)
                            mresult.restricted = false;
                        if (!mresult.asked)
                            mresult.asked = (hook.whitelist() == null);
                    }
                // Check whitelist
                if (usage && hook != null && hook.whitelist() != null && restriction.extra != null) {
                    String value = getSetting(new PSetting(restriction.uid, hook.whitelist(), restriction.extra, null)).value;
                    if (value == null) {
                        for (String xextra : getXExtra(restriction, hook)) {
                            value = getSetting(new PSetting(restriction.uid, hook.whitelist(), xextra, null)).value;
                            if (value != null)
                                break;
                        }
                    }
                    if (value != null) {
                        // true means allow, false means block
                        mresult.restricted = !Boolean.parseBoolean(value);
                        mresult.asked = true;
                    }
                }
                // Fallback
                if (!mresult.restricted && usage && PrivacyManager.isApplication(restriction.uid) && !getSettingBool(userId, PrivacyManager.cSettingMigrated, false)) {
                    if (hook != null && !hook.isDangerous()) {
                        mresult.restricted = PrivacyProvider.getRestrictedFallback(null, restriction.uid, restriction.restrictionName, restriction.methodName);
                        Util.log(null, Log.WARN, "Fallback " + mresult);
                    }
                }
                // Update cache
                CRestriction cukey = new CRestriction(cresult, null);
                synchronized (mRestrictionCache) {
                    if (mRestrictionCache.containsKey(cukey))
                        mRestrictionCache.remove(cukey);
                    mRestrictionCache.put(cukey, cukey);
                }
                CRestriction ukey = new CRestriction(mresult, restriction.extra);
                synchronized (mRestrictionCache) {
                    if (mRestrictionCache.containsKey(ukey))
                        mRestrictionCache.remove(ukey);
                    mRestrictionCache.put(ukey, ukey);
                }
            }
            // Ask to restrict
            OnDemandResult oResult = new OnDemandResult();
            if (!mresult.asked && usage) {
                oResult = onDemandDialog(hook, restriction, mresult);
                // Update cache
                if (oResult.ondemand && !oResult.once) {
                    CRestriction okey = new CRestriction(mresult, oResult.whitelist ? restriction.extra : null);
                    synchronized (mRestrictionCache) {
                        if (mRestrictionCache.containsKey(okey))
                            mRestrictionCache.remove(okey);
                        mRestrictionCache.put(okey, okey);
                    }
                }
            }
            // Notify user
            if (!oResult.ondemand && mresult.restricted && usage && hook != null && hook.shouldNotify()) {
                notifyRestricted(restriction);
                mresult.time = new Date().getTime();
            }
        }
        // Store usage data
        if (usage && hook != null)
            storeUsageData(restriction, secret, mresult);
    } catch (SQLiteException ex) {
        notifyException(ex);
    } catch (Throwable ex) {
        Util.bug(null, ex);
    } finally {
        StrictMode.setThreadPolicy(oldPolicy);
    }
    long ms = System.currentTimeMillis() - start;
    Util.log(null, ms < PrivacyManager.cWarnServiceDelayMs ? Log.INFO : Log.WARN, String.format("Get service %s%s %d ms", restriction, (ccached ? " (ccached)" : "") + (mcached ? " (mcached)" : ""), ms));
    if (mresult.debug)
        Util.logStack(null, Log.WARN);
    if (usage) {
        mCount.incrementAndGet();
        if (mresult.restricted)
            mRestricted.incrementAndGet();
    }
    return mresult;
}
Also used : ThreadPolicy(android.os.StrictMode.ThreadPolicy) SQLiteDoneException(android.database.sqlite.SQLiteDoneException) SQLiteException(android.database.sqlite.SQLiteException) SuppressLint(android.annotation.SuppressLint) Date(java.util.Date) SQLiteDatabase(android.database.sqlite.SQLiteDatabase)

Aggregations

ThreadPolicy (android.os.StrictMode.ThreadPolicy)7 File (java.io.File)4 FilenameFilter (java.io.FilenameFilter)4 Pattern (java.util.regex.Pattern)4 SuppressLint (android.annotation.SuppressLint)2 SQLiteDatabase (android.database.sqlite.SQLiteDatabase)2 SQLiteDoneException (android.database.sqlite.SQLiteDoneException)2 SQLiteException (android.database.sqlite.SQLiteException)2 TargetApi (android.annotation.TargetApi)1 Date (java.util.Date)1