summaryrefslogtreecommitdiffstats
path: root/packages
diff options
context:
space:
mode:
Diffstat (limited to 'packages')
-rw-r--r--packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java153
-rw-r--r--packages/SettingsProvider/res/values/defaults.xml2
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java84
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java6
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java4
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java152
-rwxr-xr-xpackages/TtsService/src/android/tts/SynthProxy.java8
7 files changed, 277 insertions, 132 deletions
diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
index 02e1f07..4635f48 100644
--- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
+++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
@@ -5,6 +5,7 @@ import com.android.internal.content.PackageHelper;
import android.content.Intent;
import android.content.pm.IPackageManager;
import android.content.pm.PackageInfo;
+import android.content.pm.PackageInfoLite;
import android.content.pm.PackageManager;
import android.content.pm.PackageParser;
import android.content.pm.PackageParser.Package;
@@ -28,6 +29,7 @@ import java.io.IOException;
import java.io.InputStream;
import android.os.FileUtils;
+import android.os.storage.IMountService;
import android.provider.Settings;
/*
@@ -86,46 +88,51 @@ public class DefaultContainerService extends IntentService {
* specified by file uri location.
* @param fileUri the uri of resource to be copied. Should be a
* file uri
- * @return Returns
- * PackageHelper.RECOMMEND_INSTALL_INTERNAL to install on internal storage
- * PackageHelper.RECOMMEND_INSTALL_EXTERNAL to install on external media
- * PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE for storage errors
- * PackageHelper.RECOMMEND_FAILED_INVALID_APK for parse errors.
+ * @return Returns PackageInfoLite object containing
+ * the package info and recommended app location.
*/
- public int getRecommendedInstallLocation(final Uri fileUri) {
+ public PackageInfoLite getMinimalPackageInfo(final Uri fileUri) {
+ PackageInfoLite ret = new PackageInfoLite();
if (fileUri == null) {
Log.i(TAG, "Invalid package uri " + fileUri);
- return PackageHelper.RECOMMEND_FAILED_INVALID_APK;
+ ret.recommendedInstallLocation = PackageHelper.RECOMMEND_FAILED_INVALID_APK;
+ return ret;
}
String scheme = fileUri.getScheme();
if (scheme != null && !scheme.equals("file")) {
Log.w(TAG, "Falling back to installing on internal storage only");
- return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
+ ret.recommendedInstallLocation = PackageHelper.RECOMMEND_INSTALL_INTERNAL;
+ return ret;
}
String archiveFilePath = fileUri.getPath();
PackageParser packageParser = new PackageParser(archiveFilePath);
File sourceFile = new File(archiveFilePath);
DisplayMetrics metrics = new DisplayMetrics();
metrics.setToDefaults();
- PackageParser.Package pkg = packageParser.parsePackage(sourceFile,
- archiveFilePath, metrics, 0);
+ PackageParser.PackageLite pkg = packageParser.parsePackageLite(
+ archiveFilePath, 0);
+ ret.packageName = pkg.packageName;
+ ret.installLocation = pkg.installLocation;
// Nuke the parser reference right away and force a gc
Runtime.getRuntime().gc();
packageParser = null;
if (pkg == null) {
Log.w(TAG, "Failed to parse package");
- return PackageHelper.RECOMMEND_FAILED_INVALID_APK;
+ ret.recommendedInstallLocation = PackageHelper.RECOMMEND_FAILED_INVALID_APK;
+ return ret;
}
- int loc = recommendAppInstallLocation(pkg);
+ ret.packageName = pkg.packageName;
+ int loc = recommendAppInstallLocation(pkg.installLocation, archiveFilePath);
if (loc == PackageManager.INSTALL_EXTERNAL) {
- return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
+ ret.recommendedInstallLocation = PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
} else if (loc == ERR_LOC) {
Log.i(TAG, "Failed to install insufficient storage");
- return PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE;
+ ret.recommendedInstallLocation = PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE;
} else {
// Implies install on internal storage.
- return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
+ ret.recommendedInstallLocation = PackageHelper.RECOMMEND_INSTALL_INTERNAL;
}
+ return ret;
}
};
@@ -171,62 +178,37 @@ public class DefaultContainerService extends IntentService {
String codePath = packageURI.getPath();
File codeFile = new File(codePath);
String newCachePath = null;
- final int CREATE_FAILED = 1;
- final int COPY_FAILED = 2;
- final int FINALIZE_FAILED = 3;
- final int PASS = 4;
- int errCode = CREATE_FAILED;
// Create new container
if ((newCachePath = PackageHelper.createSdDir(codeFile,
- newCid, key, Process.myUid())) != null) {
- if (localLOGV) Log.i(TAG, "Created container for " + newCid
- + " at path : " + newCachePath);
- File resFile = new File(newCachePath, resFileName);
- errCode = COPY_FAILED;
- // Copy file from codePath
- if (FileUtils.copyFile(new File(codePath), resFile)) {
- if (localLOGV) Log.i(TAG, "Copied " + codePath + " to " + resFile);
- errCode = FINALIZE_FAILED;
- if (PackageHelper.finalizeSdDir(newCid)) {
- if (localLOGV) Log.i(TAG, "Finalized container " + newCid);
- errCode = PASS;
- }
- }
- }
- // Print error based on errCode
- String errMsg = "";
- switch (errCode) {
- case CREATE_FAILED:
- errMsg = "CREATE_FAILED";
- break;
- case COPY_FAILED:
- errMsg = "COPY_FAILED";
- if (localLOGV) Log.i(TAG, "Destroying " + newCid +
- " at path " + newCachePath + " after " + errMsg);
- PackageHelper.destroySdDir(newCid);
- break;
- case FINALIZE_FAILED:
- errMsg = "FINALIZE_FAILED";
- if (localLOGV) Log.i(TAG, "Destroying " + newCid +
- " at path " + newCachePath + " after " + errMsg);
- PackageHelper.destroySdDir(newCid);
- break;
- default:
- errMsg = "PASS";
- if (PackageHelper.isContainerMounted(newCid)) {
- if (localLOGV) Log.i(TAG, "Unmounting " + newCid +
- " at path " + newCachePath + " after " + errMsg);
- // Force a gc to avoid being killed.
- Runtime.getRuntime().gc();
- PackageHelper.unMountSdDir(newCid);
- } else {
- if (localLOGV) Log.i(TAG, "Container " + newCid + " not mounted");
- }
- break;
+ newCid, key, Process.myUid())) == null) {
+ Log.e(TAG, "Failed to create container " + newCid);
+ return null;
}
- if (errCode != PASS) {
+ if (localLOGV) Log.i(TAG, "Created container for " + newCid
+ + " at path : " + newCachePath);
+ File resFile = new File(newCachePath, resFileName);
+ if (!FileUtils.copyFile(new File(codePath), resFile)) {
+ Log.e(TAG, "Failed to copy " + codePath + " to " + resFile);
+ // Clean up container
+ PackageHelper.destroySdDir(newCid);
return null;
}
+ if (localLOGV) Log.i(TAG, "Copied " + codePath + " to " + resFile);
+ if (!PackageHelper.finalizeSdDir(newCid)) {
+ Log.e(TAG, "Failed to finalize " + newCid + " at path " + newCachePath);
+ // Clean up container
+ PackageHelper.destroySdDir(newCid);
+ }
+ if (localLOGV) Log.i(TAG, "Finalized container " + newCid);
+ if (PackageHelper.isContainerMounted(newCid)) {
+ if (localLOGV) Log.i(TAG, "Unmounting " + newCid +
+ " at path " + newCachePath);
+ // Force a gc to avoid being killed.
+ Runtime.getRuntime().gc();
+ PackageHelper.unMountSdDir(newCid);
+ } else {
+ if (localLOGV) Log.i(TAG, "Container " + newCid + " not mounted");
+ }
return newCachePath;
}
@@ -307,29 +289,28 @@ public class DefaultContainerService extends IntentService {
private static final long INSTALL_ON_SD_THRESHOLD = (1024 * 1024);
private static final int ERR_LOC = -1;
- public int recommendAppInstallLocation(Package pkg) {
+ private int recommendAppInstallLocation(int installLocation,
+ String archiveFilePath) {
// Initial implementation:
// Package size = code size + cache size + data size
// If code size > 1 MB, install on SD card.
// Else install on internal NAND flash, unless space on NAND is less than 10%
-
- if (pkg == null) {
- return ERR_LOC;
+ String status = Environment.getExternalStorageState();
+ long availSDSize = -1;
+ if (status.equals(Environment.MEDIA_MOUNTED)) {
+ StatFs sdStats = new StatFs(
+ Environment.getExternalStorageDirectory().getPath());
+ availSDSize = (long)sdStats.getAvailableBlocks() *
+ (long)sdStats.getBlockSize();
}
+ StatFs internalStats = new StatFs(Environment.getDataDirectory().getPath());
+ long totalInternalSize = (long)internalStats.getBlockCount() *
+ (long)internalStats.getBlockSize();
+ long availInternalSize = (long)internalStats.getAvailableBlocks() *
+ (long)internalStats.getBlockSize();
- StatFs internalFlashStats = new StatFs(Environment.getDataDirectory().getPath());
- StatFs sdcardStats = new StatFs(Environment.getExternalStorageDirectory().getPath());
-
- long totalInternalFlashSize = (long)internalFlashStats.getBlockCount() *
- (long)internalFlashStats.getBlockSize();
- long availInternalFlashSize = (long)internalFlashStats.getAvailableBlocks() *
- (long)internalFlashStats.getBlockSize();
- long availSDSize = (long)sdcardStats.getAvailableBlocks() *
- (long)sdcardStats.getBlockSize();
-
- double pctNandFree = (double)availInternalFlashSize / (double)totalInternalFlashSize;
+ double pctNandFree = (double)availInternalSize / (double)totalInternalSize;
- final String archiveFilePath = pkg.mScanPath;
File apkFile = new File(archiveFilePath);
long pkgLen = apkFile.length();
@@ -339,15 +320,15 @@ public class DefaultContainerService extends IntentService {
// For dex files. Just ignore and fail when extracting. Max limit of 2Gig for now.
long reqInternalSize = 0;
boolean intThresholdOk = (pctNandFree >= LOW_NAND_FLASH_TRESHOLD);
- boolean intAvailOk = ((reqInstallSize + reqInternalSize) < availInternalFlashSize);
+ boolean intAvailOk = ((reqInstallSize + reqInternalSize) < availInternalSize);
boolean fitsOnSd = (reqInstallSize < availSDSize) && intThresholdOk &&
- (reqInternalSize < availInternalFlashSize);
+ (reqInternalSize < availInternalSize);
boolean fitsOnInt = intThresholdOk && intAvailOk;
// Consider application flags preferences as well...
- boolean installOnlyOnSd = (pkg.installLocation ==
+ boolean installOnlyOnSd = (installLocation ==
PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
- boolean installOnlyInternal = (pkg.installLocation ==
+ boolean installOnlyInternal = (installLocation ==
PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
if (installOnlyInternal) {
// If set explicitly in manifest,
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 1e9c312..bd131e0 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -60,7 +60,7 @@
<!-- user interface sound effects -->
<integer name="def_power_sounds_enabled">1</integer>
- <string name="def_low_battery_sound" translatable="false">/system/media/ui/LowBattery.ogg</string>
+ <string name="def_low_battery_sound" translatable="false">/system/media/audio/ui/LowBattery.ogg</string>
<integer name="def_dock_sounds_enabled">0</integer>
<string name="def_desk_dock_sound" translatable="false">/system/media/audio/ui/Dock.ogg</string>
<string name="def_desk_undock_sound" translatable="false">/system/media/audio/ui/Undock.ogg</string>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 18e247e..bccf7d2 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -38,6 +38,7 @@ import android.net.ConnectivityManager;
import android.os.Environment;
import android.os.SystemProperties;
import android.provider.Settings;
+import android.provider.Settings.Secure;
import android.speech.RecognitionService;
import android.speech.RecognizerIntent;
import android.text.TextUtils;
@@ -76,7 +77,7 @@ public class DatabaseHelper extends SQLiteOpenHelper {
// database gets upgraded properly. At a minimum, please confirm that 'upgradeVersion'
// is properly propagated through your change. Not doing so will result in a loss of user
// settings.
- private static final int DATABASE_VERSION = 51;
+ private static final int DATABASE_VERSION = 52;
private Context mContext;
@@ -232,18 +233,7 @@ public class DatabaseHelper extends SQLiteOpenHelper {
}
if (upgradeVersion == 27) {
- // Copy settings values from 'system' to 'secure' and delete them from 'system'
- SQLiteStatement insertStmt = null;
- SQLiteStatement deleteStmt = null;
-
- db.beginTransaction();
- try {
- insertStmt =
- db.compileStatement("INSERT INTO secure (name,value) SELECT name,value FROM "
- + "system WHERE name=?");
- deleteStmt = db.compileStatement("DELETE FROM system WHERE name=?");
-
- String[] settingsToMove = {
+ String[] settingsToMove = {
Settings.Secure.ADB_ENABLED,
Settings.Secure.ANDROID_ID,
Settings.Secure.BLUETOOTH_ON,
@@ -276,24 +266,7 @@ public class DatabaseHelper extends SQLiteOpenHelper {
Settings.Secure.WIFI_WATCHDOG_PING_DELAY_MS,
Settings.Secure.WIFI_WATCHDOG_PING_TIMEOUT_MS,
};
-
- for (String setting : settingsToMove) {
- insertStmt.bindString(1, setting);
- insertStmt.execute();
-
- deleteStmt.bindString(1, setting);
- deleteStmt.execute();
- }
- db.setTransactionSuccessful();
- } finally {
- db.endTransaction();
- if (insertStmt != null) {
- insertStmt.close();
- }
- if (deleteStmt != null) {
- deleteStmt.close();
- }
- }
+ moveFromSystemToSecure(db, settingsToMove);
upgradeVersion = 28;
}
@@ -661,6 +634,23 @@ public class DatabaseHelper extends SQLiteOpenHelper {
upgradeVersion = 51;
}
+ if (upgradeVersion == 51) {
+ /* Move the lockscreen related settings to Secure, including some private ones. */
+ String[] settingsToMove = {
+ Secure.LOCK_PATTERN_ENABLED,
+ Secure.LOCK_PATTERN_VISIBLE,
+ Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED,
+ "lockscreen.password_type",
+ "lockscreen.lockoutattemptdeadline",
+ "lockscreen.patterneverchosen",
+ "lock_pattern_autolock",
+ "lockscreen.lockedoutpermanently",
+ "lockscreen.password_salt"
+ };
+ moveFromSystemToSecure(db, settingsToMove);
+ upgradeVersion = 52;
+ }
+
if (upgradeVersion != currentVersion) {
Log.w(TAG, "Got stuck trying to upgrade from version " + upgradeVersion
+ ", must wipe the settings provider");
@@ -684,6 +674,38 @@ public class DatabaseHelper extends SQLiteOpenHelper {
}
}
+ private void moveFromSystemToSecure(SQLiteDatabase db, String [] settingsToMove) {
+ // Copy settings values from 'system' to 'secure' and delete them from 'system'
+ SQLiteStatement insertStmt = null;
+ SQLiteStatement deleteStmt = null;
+
+ db.beginTransaction();
+ try {
+ insertStmt =
+ db.compileStatement("INSERT INTO secure (name,value) SELECT name,value FROM "
+ + "system WHERE name=?");
+ deleteStmt = db.compileStatement("DELETE FROM system WHERE name=?");
+
+
+ for (String setting : settingsToMove) {
+ insertStmt.bindString(1, setting);
+ insertStmt.execute();
+
+ deleteStmt.bindString(1, setting);
+ deleteStmt.execute();
+ }
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ if (insertStmt != null) {
+ insertStmt.close();
+ }
+ if (deleteStmt != null) {
+ deleteStmt.close();
+ }
+ }
+ }
+
private void upgradeLockPatternLocation(SQLiteDatabase db) {
Cursor c = db.query("system", new String[] {"_id", "value"}, "name='lock_pattern'",
null, null, null, null);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
index 2738efb..d5c9855 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
@@ -30,9 +30,9 @@ import java.io.IOException;
import java.util.Arrays;
import java.util.zip.CRC32;
-import android.backup.BackupDataInput;
-import android.backup.BackupDataOutput;
-import android.backup.BackupHelperAgent;
+import android.app.backup.BackupDataInput;
+import android.app.backup.BackupDataOutput;
+import android.app.backup.BackupHelperAgent;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
index d24814d..0e75fbc 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
@@ -20,8 +20,8 @@ import java.util.Locale;
import android.app.ActivityManagerNative;
import android.app.IActivityManager;
-import android.backup.BackupDataInput;
-import android.backup.IBackupManager;
+import android.app.backup.BackupDataInput;
+import android.app.backup.IBackupManager;
import android.content.ContentResolver;
import android.content.Context;
import android.content.IContentService;
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index db802d3..942d32d 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -20,8 +20,10 @@ import java.io.FileNotFoundException;
import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
+import java.util.LinkedHashMap;
+import java.util.Map;
-import android.backup.BackupManager;
+import android.app.backup.BackupManager;
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
@@ -30,9 +32,11 @@ import android.content.pm.PackageManager;
import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteQueryBuilder;
import android.media.RingtoneManager;
import android.net.Uri;
+import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.os.SystemProperties;
import android.provider.DrmStore;
@@ -48,6 +52,16 @@ public class SettingsProvider extends ContentProvider {
private static final String TABLE_FAVORITES = "favorites";
private static final String TABLE_OLD_FAVORITES = "old_favorites";
+ private static final String[] COLUMN_VALUE = new String[] { "value" };
+
+ // Cache for settings, access-ordered for acting as LRU.
+ // Guarded by themselves.
+ private static final int MAX_CACHE_ENTRIES = 50;
+ private static final SettingsCache sSystemCache = new SettingsCache();
+ private static final SettingsCache sSecureCache = new SettingsCache();
+
+ private static final Bundle NULL_SETTING = Bundle.forPair("value", null);
+
protected DatabaseHelper mOpenHelper;
private BackupManager mBackupManager;
@@ -189,7 +203,7 @@ public class SettingsProvider extends ContentProvider {
final Cursor c = query(Settings.Secure.CONTENT_URI,
new String[] { Settings.NameValueTable.VALUE },
Settings.NameValueTable.NAME + "=?",
- new String[]{Settings.Secure.ANDROID_ID}, null);
+ new String[] { Settings.Secure.ANDROID_ID }, null);
try {
final String value = c.moveToNext() ? c.getString(0) : null;
if (value == null) {
@@ -220,6 +234,51 @@ public class SettingsProvider extends ContentProvider {
}
}
+ /**
+ * Fast path that avoids the use of chatty remoted Cursors.
+ */
+ @Override
+ public Bundle call(String method, String request, Bundle args) {
+ if (Settings.CALL_METHOD_GET_SYSTEM.equals(method)) {
+ return lookupValue("system", sSystemCache, request);
+ }
+ if (Settings.CALL_METHOD_GET_SECURE.equals(method)) {
+ return lookupValue("secure", sSecureCache, request);
+ }
+ return null;
+ }
+
+ // Looks up value 'key' in 'table' and returns either a single-pair Bundle,
+ // possibly with a null value, or null on failure.
+ private Bundle lookupValue(String table, SettingsCache cache, String key) {
+ synchronized (cache) {
+ if (cache.containsKey(key)) {
+ return cache.get(key);
+ }
+ }
+
+ SQLiteDatabase db = mOpenHelper.getReadableDatabase();
+ Cursor cursor = null;
+ try {
+ cursor = db.query(table, COLUMN_VALUE, "name=?", new String[]{key},
+ null, null, null, null);
+ if (cursor != null && cursor.getCount() == 1) {
+ cursor.moveToFirst();
+ String value = cursor.getString(0);
+ Bundle bundle = (value == null) ? NULL_SETTING : Bundle.forPair("value", value);
+ cache.putIfAbsentLocked(key, bundle);
+ return bundle;
+ }
+ } catch (SQLiteException e) {
+ Log.w(TAG, "settings lookup error", e);
+ return null;
+ } finally {
+ if (cursor != null) cursor.close();
+ }
+ cache.putIfAbsentLocked(key, NULL_SETTING);
+ return NULL_SETTING;
+ }
+
@Override
public Cursor query(Uri url, String[] select, String where, String[] whereArgs, String sort) {
SqlArguments args = new SqlArguments(url, where, whereArgs);
@@ -271,6 +330,7 @@ public class SettingsProvider extends ContentProvider {
return 0;
}
checkWritePermissions(args);
+ SettingsCache cache = SettingsCache.forTable(args.table);
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
db.beginTransaction();
@@ -278,6 +338,7 @@ public class SettingsProvider extends ContentProvider {
int numValues = values.length;
for (int i = 0; i < numValues; i++) {
if (db.insert(args.table, null, values[i]) < 0) return 0;
+ SettingsCache.populate(cache, values[i]);
if (LOCAL_LOGV) Log.v(TAG, args.table + " <- " + values[i]);
}
db.setTransactionSuccessful();
@@ -294,6 +355,9 @@ public class SettingsProvider extends ContentProvider {
* This setting contains a list of the currently enabled location providers.
* But helper functions in android.providers.Settings can enable or disable
* a single provider by using a "+" or "-" prefix before the provider name.
+ *
+ * @returns whether the database needs to be updated or not, also modifying
+ * 'initialValues' if needed.
*/
private boolean parseProviderList(Uri url, ContentValues initialValues) {
String value = initialValues.getAsString(Settings.Secure.VALUE);
@@ -351,7 +415,7 @@ public class SettingsProvider extends ContentProvider {
}
}
}
-
+
return true;
}
@@ -374,6 +438,9 @@ public class SettingsProvider extends ContentProvider {
final long rowId = db.insert(args.table, null, initialValues);
if (rowId <= 0) return null;
+ SettingsCache cache = SettingsCache.forTable(args.table);
+ SettingsCache.populate(cache, initialValues); // before we notify
+
if (LOCAL_LOGV) Log.v(TAG, args.table + " <- " + initialValues);
url = getUriFor(url, initialValues, rowId);
sendNotify(url);
@@ -392,7 +459,10 @@ public class SettingsProvider extends ContentProvider {
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
int count = db.delete(args.table, args.where, args.args);
- if (count > 0) sendNotify(url);
+ if (count > 0) {
+ SettingsCache.wipe(args.table); // before we notify
+ sendNotify(url);
+ }
if (LOCAL_LOGV) Log.v(TAG, args.table + ": " + count + " row(s) deleted");
return count;
}
@@ -407,7 +477,10 @@ public class SettingsProvider extends ContentProvider {
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
int count = db.update(args.table, initialValues, args.where, args.args);
- if (count > 0) sendNotify(url);
+ if (count > 0) {
+ SettingsCache.wipe(args.table); // before we notify
+ sendNotify(url);
+ }
if (LOCAL_LOGV) Log.v(TAG, args.table + ": " + count + " row(s) <- " + initialValues);
return count;
}
@@ -512,4 +585,73 @@ public class SettingsProvider extends ContentProvider {
// Note that this will end up calling openFile() above.
return super.openAssetFile(uri, mode);
}
+
+ /**
+ * In-memory LRU Cache of system and secure settings, along with
+ * associated helper functions to keep cache coherent with the
+ * database.
+ */
+ private static final class SettingsCache extends LinkedHashMap<String, Bundle> {
+ public SettingsCache() {
+ super(MAX_CACHE_ENTRIES, 0.75f /* load factor */, true /* access ordered */);
+ }
+
+ @Override
+ protected boolean removeEldestEntry(Map.Entry eldest) {
+ return size() > MAX_CACHE_ENTRIES;
+ }
+
+ public void putIfAbsentLocked(String key, Bundle value) {
+ synchronized (this) {
+ if (containsKey(key)) {
+ // Lost a race.
+ return;
+ }
+ put(key, value);
+ }
+ }
+
+ public static SettingsCache forTable(String tableName) {
+ if ("system".equals(tableName)) {
+ return SettingsProvider.sSystemCache;
+ }
+ if ("secure".equals(tableName)) {
+ return SettingsProvider.sSecureCache;
+ }
+ return null;
+ }
+
+ /**
+ * Populates a key in a given (possibly-null) cache.
+ */
+ public static void populate(SettingsCache cache, ContentValues contentValues) {
+ if (cache == null) {
+ return;
+ }
+ String name = contentValues.getAsString(Settings.NameValueTable.NAME);
+ if (name == null) {
+ Log.w(TAG, "null name populating settings cache.");
+ return;
+ }
+ String value = contentValues.getAsString(Settings.NameValueTable.VALUE);
+ synchronized (cache) {
+ cache.put(name, Bundle.forPair(Settings.NameValueTable.VALUE, value));
+ }
+ }
+
+ /**
+ * Used for wiping a whole cache on deletes when we're not
+ * sure what exactly was deleted or changed.
+ */
+ public static void wipe(String tableName) {
+ SettingsCache cache = SettingsCache.forTable(tableName);
+ if (cache == null) {
+ return;
+ }
+ synchronized (cache) {
+ cache.clear();
+ }
+ }
+
+ }
}
diff --git a/packages/TtsService/src/android/tts/SynthProxy.java b/packages/TtsService/src/android/tts/SynthProxy.java
index 6255275..cd46c05 100755
--- a/packages/TtsService/src/android/tts/SynthProxy.java
+++ b/packages/TtsService/src/android/tts/SynthProxy.java
@@ -36,9 +36,9 @@ public class SynthProxy {
// Such a huge filter gain is justified by how much energy in the low frequencies is "wasted" at
// the output of the synthesis. The low shelving filter removes it, leaving room for
// amplification.
- private final static float PICO_FILTER_GAIN = 5.5f; // linear gain
- private final static float PICO_FILTER_LOWSHELF_ATTENUATION = -18.0f; // in dB
- private final static float PICO_FILTER_TRANSITION_FREQ = 1100.0f; // in Hz
+ private final static float PICO_FILTER_GAIN = 4.0f; // linear gain
+ private final static float PICO_FILTER_LOWSHELF_ATTENUATION = -16.0f; // in dB
+ private final static float PICO_FILTER_TRANSITION_FREQ = 1000.0f; // in Hz
private final static float PICO_FILTER_SHELF_SLOPE = 1.0f; // Q
//
@@ -50,7 +50,7 @@ public class SynthProxy {
*/
public SynthProxy(String nativeSoLib) {
boolean applyFilter = nativeSoLib.toLowerCase().contains("pico");
- Log.v(TtsService.SERVICE_TAG, "about to load "+ nativeSoLib + ", applyFilter="+applyFilter);
+ Log.v(TtsService.SERVICE_TAG, "About to load "+ nativeSoLib + ", applyFilter="+applyFilter);
native_setup(new WeakReference<SynthProxy>(this), nativeSoLib);
native_setLowShelf(applyFilter, PICO_FILTER_GAIN, PICO_FILTER_LOWSHELF_ATTENUATION,
PICO_FILTER_TRANSITION_FREQ, PICO_FILTER_SHELF_SLOPE);