diff options
Diffstat (limited to 'packages')
37 files changed, 445 insertions, 220 deletions
diff --git a/packages/SettingsProvider/AndroidManifest.xml b/packages/SettingsProvider/AndroidManifest.xml index d84572b..af0a1bd 100644 --- a/packages/SettingsProvider/AndroidManifest.xml +++ b/packages/SettingsProvider/AndroidManifest.xml @@ -2,6 +2,8 @@ package="com.android.providers.settings" android:sharedUserId="android.uid.system"> + <uses-permission android:name="android.permission.BACKUP_DATA" /> + <application android:allowClearUserData="false" android:label="@string/app_label" android:process="system" diff --git a/packages/SettingsProvider/etc/bookmarks.xml b/packages/SettingsProvider/etc/bookmarks.xml index 5af416a..734e0cd 100644 --- a/packages/SettingsProvider/etc/bookmarks.xml +++ b/packages/SettingsProvider/etc/bookmarks.xml @@ -39,10 +39,12 @@ package="com.android.calendar" class="com.android.calendar.LaunchActivity" shortcut="l" /> +<!-- <bookmark package="com.google.android.apps.maps" class="com.google.android.maps.MapsActivity" shortcut="m" /> +--> <bookmark package="com.android.music" class="com.android.music.MusicBrowserActivity" diff --git a/packages/SettingsProvider/res/values-ja/strings.xml b/packages/SettingsProvider/res/values-ja/strings.xml deleted file mode 100644 index ffd57e6..0000000 --- a/packages/SettingsProvider/res/values-ja/strings.xml +++ /dev/null @@ -1,19 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2009 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="app_label" msgid="4567566098528588863">"ストレージの設定"</string> -</resources> diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml index f60ea57..6b20445 100644 --- a/packages/SettingsProvider/res/values/defaults.xml +++ b/packages/SettingsProvider/res/values/defaults.xml @@ -22,6 +22,7 @@ <bool name="def_airplane_mode_on">false</bool> <!-- Comma-separated list of bluetooth, wifi, and cell. --> <string name="def_airplane_mode_radios" translatable="false">cell,bluetooth,wifi</string> + <string name="airplane_mode_toggleable_radios" translatable="false">wifi</string> <bool name="def_auto_time">true</bool> <bool name="def_accelerometer_rotation">true</bool> <!-- Default screen brightness, from 0 to 255. 102 is 40%. --> @@ -36,6 +37,7 @@ user opt-in via Setup Wizard or Settings. --> <string name="def_location_providers_allowed" translatable="false">gps</string> + <bool name="assisted_gps_enabled">true</bool> <!-- 0 == mobile, 1 == wifi. --> <integer name="def_network_preference">1</integer> <bool name="def_usb_mass_storage_enabled">true</bool> diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java index 6dd1175..8f4061e 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java @@ -56,7 +56,7 @@ import java.util.List; * Database helper class for {@link SettingsProvider}. * Mostly just has a bit {@link #onCreate} to initialize the database. */ -class DatabaseHelper extends SQLiteOpenHelper { +public class DatabaseHelper extends SQLiteOpenHelper { /** * Path to file containing default bookmarks, relative to ANDROID_ROOT. */ @@ -64,7 +64,7 @@ class DatabaseHelper extends SQLiteOpenHelper { private static final String TAG = "SettingsProvider"; private static final String DATABASE_NAME = "settings.db"; - private static final int DATABASE_VERSION = 35; + private static final int DATABASE_VERSION = 39; private Context mContext; @@ -397,9 +397,66 @@ class DatabaseHelper extends SQLiteOpenHelper { } finally { db.endTransaction(); } - upgradeVersion = 35; } - + // due to a botched merge from donut to eclair, the initialization of ASSISTED_GPS_ENABLED + // was accidentally done out of order here. + // to fix this, ASSISTED_GPS_ENABLED is now initialized while upgrading from 38 to 39, + // and we intentionally do nothing from 35 to 36 now. + if (upgradeVersion == 35) { + upgradeVersion = 36; + } + + if (upgradeVersion == 36) { + // This upgrade adds the STREAM_SYSTEM_ENFORCED type to the list of + // types affected by ringer modes (silent, vibrate, etc.) + db.beginTransaction(); + try { + db.execSQL("DELETE FROM system WHERE name='" + + Settings.System.MODE_RINGER_STREAMS_AFFECTED + "'"); + int newValue = (1 << AudioManager.STREAM_RING) + | (1 << AudioManager.STREAM_NOTIFICATION) + | (1 << AudioManager.STREAM_SYSTEM) + | (1 << AudioManager.STREAM_SYSTEM_ENFORCED); + db.execSQL("INSERT INTO system ('name', 'value') values ('" + + Settings.System.MODE_RINGER_STREAMS_AFFECTED + "', '" + + String.valueOf(newValue) + "')"); + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + } + upgradeVersion = 37; + } + + if (upgradeVersion == 37) { + db.beginTransaction(); + try { + SQLiteStatement stmt = db.compileStatement("INSERT OR IGNORE INTO system(name,value)" + + " VALUES(?,?);"); + loadStringSetting(stmt, Settings.System.AIRPLANE_MODE_TOGGLEABLE_RADIOS, + R.string.airplane_mode_toggleable_radios); + stmt.close(); + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + } + upgradeVersion = 38; + } + + if (upgradeVersion == 38) { + db.beginTransaction(); + try { + String value = + mContext.getResources().getBoolean(R.bool.assisted_gps_enabled) ? "1" : "0"; + db.execSQL("INSERT OR IGNORE INTO secure(name,value) values('" + + Settings.Secure.ASSISTED_GPS_ENABLED + "','" + value + "');"); + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + } + + upgradeVersion = 39; + } + if (upgradeVersion != currentVersion) { Log.w(TAG, "Got stuck trying to upgrade from version " + upgradeVersion + ", must wipe the settings provider"); @@ -560,7 +617,7 @@ class DatabaseHelper extends SQLiteOpenHelper { // By default, only the ring/notification and system streams are affected loadSetting(stmt, Settings.System.MODE_RINGER_STREAMS_AFFECTED, (1 << AudioManager.STREAM_RING) | (1 << AudioManager.STREAM_NOTIFICATION) | - (1 << AudioManager.STREAM_SYSTEM)); + (1 << AudioManager.STREAM_SYSTEM) | (1 << AudioManager.STREAM_SYSTEM_ENFORCED)); loadSetting(stmt, Settings.System.MUTE_STREAMS_AFFECTED, ((1 << AudioManager.STREAM_MUSIC) | @@ -627,6 +684,9 @@ class DatabaseHelper extends SQLiteOpenHelper { loadStringSetting(stmt, Settings.System.AIRPLANE_MODE_RADIOS, R.string.def_airplane_mode_radios); + loadStringSetting(stmt, Settings.System.AIRPLANE_MODE_TOGGLEABLE_RADIOS, + R.string.airplane_mode_toggleable_radios); + loadBooleanSetting(stmt, Settings.System.AUTO_TIME, R.bool.def_auto_time); // Sync time to NITZ @@ -667,6 +727,9 @@ class DatabaseHelper extends SQLiteOpenHelper { loadStringSetting(stmt, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, R.string.def_location_providers_allowed); + loadBooleanSetting(stmt, Settings.Secure.ASSISTED_GPS_ENABLED, + R.bool.assisted_gps_enabled); + loadIntegerSetting(stmt, Settings.Secure.NETWORK_PREFERENCE, R.integer.def_network_preference); diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java index 2b36904..56a279a 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java @@ -30,7 +30,7 @@ import java.util.zip.CRC32; import android.backup.BackupDataInput; import android.backup.BackupDataOutput; import android.backup.BackupHelperAgent; -import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothAdapter; import android.content.ContentResolver; import android.content.ContentValues; import android.content.Context; @@ -83,6 +83,11 @@ public class SettingsBackupAgent extends BackupHelperAgent { }; private static final String FILE_WIFI_SUPPLICANT = "/data/misc/wifi/wpa_supplicant.conf"; + + // the key to store the WIFI data under, should be sorted as last, so restore happens last. + // use very late unicode character to quasi-guarantee last sort position. + private static final String KEY_WIFI_SUPPLICANT = "\uffeeWIFI"; + private static final String FILE_BT_ROOT = "/data/misc/hcid/"; private SettingsHelper mSettingsHelper; @@ -113,7 +118,7 @@ public class SettingsBackupAgent extends BackupHelperAgent { stateChecksums[STATE_LOCALE] = writeIfChanged(stateChecksums[STATE_LOCALE], KEY_LOCALE, locale, data); stateChecksums[STATE_WIFI] = - writeIfChanged(stateChecksums[STATE_WIFI], FILE_WIFI_SUPPLICANT, wifiData, data); + writeIfChanged(stateChecksums[STATE_WIFI], KEY_WIFI_SUPPLICANT, wifiData, data); writeNewChecksums(stateChecksums, newState); } @@ -122,7 +127,7 @@ public class SettingsBackupAgent extends BackupHelperAgent { public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState) throws IOException { - enableWifi(false); + enableBluetooth(false); while (data.readNextHeader()) { @@ -133,12 +138,16 @@ public class SettingsBackupAgent extends BackupHelperAgent { mSettingsHelper.applyAudioSettings(); } else if (KEY_SECURE.equals(key)) { restoreSettings(data, Settings.Secure.CONTENT_URI); - } else if (FILE_WIFI_SUPPLICANT.equals(key)) { + } else if (KEY_WIFI_SUPPLICANT.equals(key)) { + int retainedWifiState = enableWifi(false); restoreFile(FILE_WIFI_SUPPLICANT, data); FileUtils.setPermissions(FILE_WIFI_SUPPLICANT, FileUtils.S_IRUSR | FileUtils.S_IWUSR | FileUtils.S_IRGRP | FileUtils.S_IWGRP, Process.myUid(), Process.WIFI_UID); + // retain the previous WIFI state. + enableWifi(retainedWifiState == WifiManager.WIFI_STATE_ENABLED || + retainedWifiState == WifiManager.WIFI_STATE_ENABLING); } else if (KEY_SYNC.equals(key)) { mSettingsHelper.setSyncProviders(data); } else if (KEY_LOCALE.equals(key)) { @@ -257,7 +266,7 @@ public class SettingsBackupAgent extends BackupHelperAgent { } /** - * Given a cursor sorted by key name and a set of keys sorted by name, + * Given a cursor sorted by key name and a set of keys sorted by name, * extract the required keys and values and write them to a byte array. * @param sortedCursor * @param sortedKeys @@ -373,15 +382,18 @@ public class SettingsBackupAgent extends BackupHelperAgent { return result; } - private void enableWifi(boolean enable) { + private int enableWifi(boolean enable) { WifiManager wfm = (WifiManager) getSystemService(Context.WIFI_SERVICE); if (wfm != null) { + int state = wfm.getWifiState(); wfm.setWifiEnabled(enable); + return state; } + return WifiManager.WIFI_STATE_UNKNOWN; } private void enableBluetooth(boolean enable) { - BluetoothDevice bt = (BluetoothDevice) getSystemService(Context.BLUETOOTH_SERVICE); + BluetoothAdapter bt = (BluetoothAdapter) getSystemService(Context.BLUETOOTH_SERVICE); if (bt != null) { if (!enable) { bt.disable(); diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java index ca739e6..b13883e 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java @@ -118,16 +118,19 @@ public class SettingsHelper { byte[] getSyncProviders() { byte[] sync = new byte[1 + PROVIDERS.length]; + // TODO: Sync backup needs to be moved to SystemBackupAgent + /* try { sync[0] = (byte) (mContentService.getListenForNetworkTickles() ? 1 : 0); for (int i = 0; i < PROVIDERS.length; i++) { sync[i + 1] = (byte) - (mContentService.getSyncProviderAutomatically(PROVIDERS[i]) ? 1 : 0); + (mContentService.getSyncAutomatically(PROVIDERS[i]) ? 1 : 0); } } catch (RemoteException re) { Log.w(TAG, "Unable to backup sync providers"); return sync; } + */ return sync; } @@ -136,12 +139,15 @@ public class SettingsHelper { try { backup.readEntityData(sync, 0, sync.length); + // TODO: Sync backup needs to be moved to SystemBackupAgent + /* mContentService.setListenForNetworkTickles(sync[0] == 1); for (int i = 0; i < PROVIDERS.length; i++) { mContentService.setSyncProviderAutomatically(PROVIDERS[i], sync[i + 1] > 0); } } catch (RemoteException re) { Log.w(TAG, "Unable to restore sync providers"); + */ } catch (java.io.IOException ioe) { Log.w(TAG, "Unable to read sync settings"); } diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java index c0de9a5..9877342 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java @@ -24,9 +24,11 @@ import android.content.ContentUris; import android.content.ContentValues; import android.content.Context; import android.content.pm.PackageManager; +import android.content.res.AssetFileDescriptor; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteQueryBuilder; +import android.media.Ringtone; import android.media.RingtoneManager; import android.net.Uri; import android.os.ParcelFileDescriptor; @@ -45,8 +47,7 @@ public class SettingsProvider extends ContentProvider { private static final String TABLE_FAVORITES = "favorites"; private static final String TABLE_OLD_FAVORITES = "old_favorites"; - private DatabaseHelper mOpenHelper; - + protected DatabaseHelper mOpenHelper; private BackupManager mBackupManager; /** @@ -398,12 +399,8 @@ public class SettingsProvider extends ContentProvider { // Get the current value for the default sound Uri soundUri = RingtoneManager.getActualDefaultRingtoneUri(context, ringtoneType); - if (soundUri == null) { - // Fallback on any valid ringtone Uri - soundUri = RingtoneManager.getValidRingtoneUri(context); - } - if (soundUri != null) { + if (soundUri != null) { // Only proxy the openFile call to drm or media providers String authority = soundUri.getAuthority(); boolean isDrmAuthority = authority.equals(DrmStore.AUTHORITY); @@ -427,4 +424,64 @@ public class SettingsProvider extends ContentProvider { return super.openFile(uri, mode); } + + @Override + public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException { + + /* + * When a client attempts to openFile the default ringtone or + * notification setting Uri, we will proxy the call to the current + * default ringtone's Uri (if it is in the DRM or media provider). + */ + int ringtoneType = RingtoneManager.getDefaultType(uri); + // Above call returns -1 if the Uri doesn't match a default type + if (ringtoneType != -1) { + Context context = getContext(); + + // Get the current value for the default sound + Uri soundUri = RingtoneManager.getActualDefaultRingtoneUri(context, ringtoneType); + + if (soundUri != null) { + // Only proxy the openFile call to drm or media providers + String authority = soundUri.getAuthority(); + boolean isDrmAuthority = authority.equals(DrmStore.AUTHORITY); + if (isDrmAuthority || authority.equals(MediaStore.AUTHORITY)) { + + if (isDrmAuthority) { + try { + // Check DRM access permission here, since once we + // do the below call the DRM will be checking our + // permission, not our caller's permission + DrmStore.enforceAccessDrmPermission(context); + } catch (SecurityException e) { + throw new FileNotFoundException(e.getMessage()); + } + } + + ParcelFileDescriptor pfd = null; + try { + pfd = context.getContentResolver().openFileDescriptor(soundUri, mode); + return new AssetFileDescriptor(pfd, 0, -1); + } catch (FileNotFoundException ex) { + // fall through and open the fallback ringtone below + } + } + + try { + return super.openAssetFile(soundUri, mode); + } catch (FileNotFoundException ex) { + // Since a non-null Uri was specified, but couldn't be opened, + // fall back to the built-in ringtone. + return context.getResources().openRawResourceFd( + com.android.internal.R.raw.fallbackring); + } + } + // no need to fall through and have openFile() try again, since we + // already know that will fail. + throw new FileNotFoundException(); // or return null ? + } + + // Note that this will end up calling openFile() above. + return super.openAssetFile(uri, mode); + } } diff --git a/packages/SubscribedFeedsProvider/AndroidManifest.xml b/packages/SubscribedFeedsProvider/AndroidManifest.xml index ca00a9b..a3938bd 100644 --- a/packages/SubscribedFeedsProvider/AndroidManifest.xml +++ b/packages/SubscribedFeedsProvider/AndroidManifest.xml @@ -13,13 +13,14 @@ android:label="@string/app_label"> <uses-library android:name="com.google.android.gtalkservice" /> <provider android:name="SubscribedFeedsProvider" - android:authorities="subscribedfeeds" android:syncable="false" + android:authorities="subscribedfeeds" + android:label="@string/provider_label" android:multiprocess="false" android:readPermission="android.permission.SUBSCRIBED_FEEDS_READ" android:writePermission="android.permission.SUBSCRIBED_FEEDS_WRITE" /> <receiver android:name="SubscribedFeedsBroadcastReceiver"> <intent-filter> - <action android:name="android.intent.action.GTALK_DATA_MESSAGE_RECEIVED" /> + <action android:name="android.intent.action.REMOTE_INTENT" /> <category android:name="GSYNC_TICKLE"/> </intent-filter> <intent-filter> diff --git a/packages/SubscribedFeedsProvider/res/values-cs/strings.xml b/packages/SubscribedFeedsProvider/res/values-cs/strings.xml index 46de1b1..9b782b0 100644 --- a/packages/SubscribedFeedsProvider/res/values-cs/strings.xml +++ b/packages/SubscribedFeedsProvider/res/values-cs/strings.xml @@ -15,5 +15,5 @@ --> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="app_label" msgid="5400580392303600842">"Synchronizace zdrojů"</string> + <string name="app_label">"Synchronizace zdrojů"</string> </resources> diff --git a/packages/SubscribedFeedsProvider/res/values-de/strings.xml b/packages/SubscribedFeedsProvider/res/values-de/strings.xml index 7e39aa8..1ade594 100644 --- a/packages/SubscribedFeedsProvider/res/values-de/strings.xml +++ b/packages/SubscribedFeedsProvider/res/values-de/strings.xml @@ -15,5 +15,5 @@ --> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="app_label" msgid="5400580392303600842">"Feedsynchronisierung"</string> + <string name="app_label">"Feedsynchronisierung"</string> </resources> diff --git a/packages/SubscribedFeedsProvider/res/values-es/strings.xml b/packages/SubscribedFeedsProvider/res/values-es/strings.xml index 9165f65..86c6946 100644 --- a/packages/SubscribedFeedsProvider/res/values-es/strings.xml +++ b/packages/SubscribedFeedsProvider/res/values-es/strings.xml @@ -15,5 +15,5 @@ --> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="app_label" msgid="5400580392303600842">"Sincronización de feeds"</string> + <string name="app_label">"Sincronización de feeds"</string> </resources> diff --git a/packages/SubscribedFeedsProvider/res/values-fr/strings.xml b/packages/SubscribedFeedsProvider/res/values-fr/strings.xml index f022e70..924b960 100644 --- a/packages/SubscribedFeedsProvider/res/values-fr/strings.xml +++ b/packages/SubscribedFeedsProvider/res/values-fr/strings.xml @@ -15,5 +15,5 @@ --> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="app_label" msgid="5400580392303600842">"Synchronisation des flux"</string> + <string name="app_label">"Synchronisation des flux"</string> </resources> diff --git a/packages/SubscribedFeedsProvider/res/values-it/strings.xml b/packages/SubscribedFeedsProvider/res/values-it/strings.xml index 1053314..eabb17e 100644 --- a/packages/SubscribedFeedsProvider/res/values-it/strings.xml +++ b/packages/SubscribedFeedsProvider/res/values-it/strings.xml @@ -15,5 +15,5 @@ --> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="app_label" msgid="5400580392303600842">"Sincronizzazione feed"</string> + <string name="app_label">"Sincronizzazione feed"</string> </resources> diff --git a/packages/SubscribedFeedsProvider/res/values-ja/strings.xml b/packages/SubscribedFeedsProvider/res/values-ja/strings.xml deleted file mode 100644 index b8f2d09..0000000 --- a/packages/SubscribedFeedsProvider/res/values-ja/strings.xml +++ /dev/null @@ -1,19 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2009 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="app_label" msgid="5400580392303600842">"フィードの同期"</string> -</resources> diff --git a/packages/SubscribedFeedsProvider/res/values-nl/strings.xml b/packages/SubscribedFeedsProvider/res/values-nl/strings.xml index 7dc5495..b9e82d1 100644 --- a/packages/SubscribedFeedsProvider/res/values-nl/strings.xml +++ b/packages/SubscribedFeedsProvider/res/values-nl/strings.xml @@ -15,5 +15,5 @@ --> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="app_label" msgid="5400580392303600842">"Feeds synchroniseren"</string> + <string name="app_label">"Feeds synchroniseren"</string> </resources> diff --git a/packages/SubscribedFeedsProvider/res/values-pl/strings.xml b/packages/SubscribedFeedsProvider/res/values-pl/strings.xml index 32c4a5e..02da9f3 100644 --- a/packages/SubscribedFeedsProvider/res/values-pl/strings.xml +++ b/packages/SubscribedFeedsProvider/res/values-pl/strings.xml @@ -15,5 +15,5 @@ --> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="app_label" msgid="5400580392303600842">"Synchronizowanie kanałów"</string> + <string name="app_label">"Synchronizowanie kanałów"</string> </resources> diff --git a/packages/SubscribedFeedsProvider/res/values-zh-rTW/strings.xml b/packages/SubscribedFeedsProvider/res/values-zh-rTW/strings.xml index 15307aa..e6643cd 100644 --- a/packages/SubscribedFeedsProvider/res/values-zh-rTW/strings.xml +++ b/packages/SubscribedFeedsProvider/res/values-zh-rTW/strings.xml @@ -15,5 +15,5 @@ --> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="app_label" msgid="5400580392303600842">"同步資訊提供"</string> + <string name="app_label">"同步資訊提供"</string> </resources> diff --git a/packages/SubscribedFeedsProvider/res/values/strings.xml b/packages/SubscribedFeedsProvider/res/values/strings.xml index 072571d..c4c2484 100644 --- a/packages/SubscribedFeedsProvider/res/values/strings.xml +++ b/packages/SubscribedFeedsProvider/res/values/strings.xml @@ -17,5 +17,9 @@ <resources> <!-- Title of the feed synchronization activity. --> <string name="app_label">Sync Feeds</string> + + <!-- What to show in messaging that refers to this provider, e.g. AccountSyncSettings --> + <string name="provider_label">Push Subscriptions</string> + </resources> diff --git a/packages/SubscribedFeedsProvider/src/com/android/providers/subscribedfeeds/SubscribedFeedsBroadcastReceiver.java b/packages/SubscribedFeedsProvider/src/com/android/providers/subscribedfeeds/SubscribedFeedsBroadcastReceiver.java index 3513215..ea14307 100644 --- a/packages/SubscribedFeedsProvider/src/com/android/providers/subscribedfeeds/SubscribedFeedsBroadcastReceiver.java +++ b/packages/SubscribedFeedsProvider/src/com/android/providers/subscribedfeeds/SubscribedFeedsBroadcastReceiver.java @@ -16,6 +16,7 @@ package com.android.providers.subscribedfeeds; +import android.app.Activity; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -35,7 +36,10 @@ public class SubscribedFeedsBroadcastReceiver extends BroadcastReceiver { public void onReceive(Context context, Intent intent) { if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "Received intent " + intent); - intent.setClass(context, SubscribedFeedsIntentService.class); + if (intent.getAction().equals(Intent.ACTION_REMOTE_INTENT)) { + setResultCode(Activity.RESULT_OK); + } + intent.setClass(context, SubscribedFeedsIntentService.class); context.startService(intent); } } diff --git a/packages/SubscribedFeedsProvider/src/com/android/providers/subscribedfeeds/SubscribedFeedsIntentService.java b/packages/SubscribedFeedsProvider/src/com/android/providers/subscribedfeeds/SubscribedFeedsIntentService.java index 8b3bedf..b854f86 100644 --- a/packages/SubscribedFeedsProvider/src/com/android/providers/subscribedfeeds/SubscribedFeedsIntentService.java +++ b/packages/SubscribedFeedsProvider/src/com/android/providers/subscribedfeeds/SubscribedFeedsIntentService.java @@ -16,13 +16,14 @@ import android.database.sqlite.SQLiteFullException; import android.app.AlarmManager; import android.app.PendingIntent; import android.os.Bundle; -import android.os.RemoteException; import android.text.TextUtils; -import android.net.Uri; +import android.accounts.Account; import java.util.ArrayList; import java.util.Calendar; +import com.google.android.collect.Lists; + /** * A service to handle various intents asynchronously. */ @@ -30,7 +31,8 @@ public class SubscribedFeedsIntentService extends IntentService { private static final String TAG = "Sync"; private static final String[] sAccountProjection = - new String[] {SubscribedFeeds.Accounts._SYNC_ACCOUNT}; + new String[] {SubscribedFeeds.Accounts._SYNC_ACCOUNT, + SubscribedFeeds.Accounts._SYNC_ACCOUNT_TYPE}; /** How often to refresh the subscriptions, in milliseconds */ private static final long SUBSCRIPTION_REFRESH_INTERVAL = 1000L * 60 * 60 * 24; // one day @@ -39,8 +41,7 @@ public class SubscribedFeedsIntentService extends IntentService { private static final String sSubscribedFeedsPrefs = "subscribedFeeds"; - private static final String GTALK_DATA_MESSAGE_RECEIVED = - "android.intent.action.GTALK_DATA_MESSAGE_RECEIVED"; + private static final String REMOTE_INTENT_ACTION = Intent.ACTION_REMOTE_INTENT; private static final String SUBSCRIBED_FEEDS_REFRESH_ACTION = "com.android.subscribedfeeds.action.REFRESH"; @@ -52,13 +53,14 @@ public class SubscribedFeedsIntentService extends IntentService { } protected void onHandleIntent(Intent intent) { - if (GTALK_DATA_MESSAGE_RECEIVED.equals(intent.getAction())) { - boolean fromTrustedServer = intent.getBooleanExtra("from_trusted_server", false); + if (REMOTE_INTENT_ACTION.equals(intent.getAction())) { + boolean fromTrustedServer = intent.getBooleanExtra( + "android.intent.extra.from_trusted_server", false); if (fromTrustedServer) { - String account = intent.getStringExtra("account"); - String token = intent.getStringExtra("message_token"); + String accountName = intent.getStringExtra("account"); + String token = intent.getStringExtra(Intent.EXTRA_REMOTE_INTENT_TOKEN); - if (TextUtils.isEmpty(account) || TextUtils.isEmpty(token)) { + if (TextUtils.isEmpty(accountName) || TextUtils.isEmpty(token)) { if (Config.LOGD) { Log.d(TAG, "Ignoring malformed tickle -- missing account or token."); } @@ -67,10 +69,10 @@ public class SubscribedFeedsIntentService extends IntentService { if (Config.LOGD) { Log.d(TAG, "Received network tickle for " - + account + " - " + token); + + accountName + " - " + token); } - handleTickle(this, account, token); + handleTickle(this, accountName, token); } else { if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "Ignoring tickle -- not from trusted server."); @@ -102,16 +104,19 @@ public class SubscribedFeedsIntentService extends IntentService { alarmManager.set(AlarmManager.RTC, when, pendingIntent); } - private void handleTickle(Context context, String account, String feed) { + private void handleTickle(Context context, String accountName, String feed) { Cursor c = null; final String where = SubscribedFeeds.Feeds._SYNC_ACCOUNT + "= ? " + + "and " + SubscribedFeeds.Feeds._SYNC_ACCOUNT_TYPE + "= ? " + "and " + SubscribedFeeds.Feeds.FEED + "= ?"; try { + // TODO(fredq) fix the hardcoded type + final Account account = new Account(accountName, "com.google.GAIA"); c = context.getContentResolver().query(SubscribedFeeds.Feeds.CONTENT_URI, - null, where, new String[]{account, feed}, null); + null, where, new String[]{account.name, account.type, feed}, null); if (c.getCount() == 0) { Log.w(TAG, "received tickle for non-existent feed: " - + "account " + account + ", feed " + feed); + + "account " + accountName + ", feed " + feed); EventLog.writeEvent(LOG_TICKLE, "unknown"); } while (c.moveToNext()) { @@ -119,21 +124,14 @@ public class SubscribedFeedsIntentService extends IntentService { String authority = c.getString(c.getColumnIndexOrThrow( SubscribedFeeds.Feeds.AUTHORITY)); EventLog.writeEvent(LOG_TICKLE, authority); - try { - if (!ContentResolver.getContentService() - .getSyncProviderAutomatically(authority)) { - Log.d(TAG, "supressing tickle since provider " + authority - + " is configured to not sync automatically"); - continue; - } - } catch (RemoteException e) { + if (!ContentResolver.getSyncAutomatically(account, authority)) { + Log.d(TAG, "supressing tickle since provider " + authority + + " is configured to not sync automatically"); continue; } - Uri uri = Uri.parse("content://" + authority); Bundle extras = new Bundle(); - extras.putString(ContentResolver.SYNC_EXTRAS_ACCOUNT, account); extras.putString("feed", feed); - context.getContentResolver().startSync(uri, extras); + ContentResolver.requestSync(account, authority, extras); } } finally { if (c != null) c.deactivate(); @@ -150,31 +148,35 @@ public class SubscribedFeedsIntentService extends IntentService { */ private void handleRefreshAlarm(Context context) { // retrieve the list of accounts from the subscribed feeds - ArrayList<String> accounts = new ArrayList<String>(); + ArrayList<Account> accounts = Lists.newArrayList(); ContentResolver contentResolver = context.getContentResolver(); Cursor c = contentResolver.query(SubscribedFeeds.Accounts.CONTENT_URI, sAccountProjection, null, null, null); - while (c.moveToNext()) { - String account = c.getString(0); - if (TextUtils.isEmpty(account)) { - continue; + try { + while (c.moveToNext()) { + String accountName = c.getString(0); + String accountType = c.getString(1); + accounts.add(new Account(accountName, accountType)); } - accounts.add(account); + } finally { + c.close(); } - c.deactivate(); // Clear the auth tokens for all these accounts so that we are sure // they will still be valid until the next time we refresh them. - // TODO: add this when the google login service is done + // TODO(fredq): add this when the google login service is done // mark the feeds dirty, by setting the accounts to the same value, // which will trigger a sync. try { ContentValues values = new ContentValues(); - for (String account : accounts) { - values.put(SyncConstValue._SYNC_ACCOUNT, account); + for (Account account : accounts) { + values.put(SyncConstValue._SYNC_ACCOUNT, account.name); + values.put(SyncConstValue._SYNC_ACCOUNT_TYPE, account.type); contentResolver.update(SubscribedFeeds.Feeds.CONTENT_URI, values, - SubscribedFeeds.Feeds._SYNC_ACCOUNT + "=?", new String[] {account}); + SubscribedFeeds.Feeds._SYNC_ACCOUNT + "=? AND " + + SubscribedFeeds.Feeds._SYNC_ACCOUNT_TYPE + "=?", + new String[] {account.name, account.type}); } } catch (SQLiteFullException e) { Log.w(TAG, "disk full while trying to mark the feeds as dirty, skipping"); diff --git a/packages/SubscribedFeedsProvider/src/com/android/providers/subscribedfeeds/SubscribedFeedsProvider.java b/packages/SubscribedFeedsProvider/src/com/android/providers/subscribedfeeds/SubscribedFeedsProvider.java index 9ecc3d6..2647752 100644 --- a/packages/SubscribedFeedsProvider/src/com/android/providers/subscribedfeeds/SubscribedFeedsProvider.java +++ b/packages/SubscribedFeedsProvider/src/com/android/providers/subscribedfeeds/SubscribedFeedsProvider.java @@ -16,6 +16,7 @@ package com.android.providers.subscribedfeeds; +import android.accounts.Account; import android.content.UriMatcher; import android.content.*; import android.database.Cursor; @@ -39,7 +40,7 @@ import java.util.HashMap; public class SubscribedFeedsProvider extends AbstractSyncableContentProvider { private static final String TAG = "SubscribedFeedsProvider"; private static final String DATABASE_NAME = "subscribedfeeds.db"; - private static final int DATABASE_VERSION = 10; + private static final int DATABASE_VERSION = 11; private static final int FEEDS = 1; private static final int FEED_ID = 2; @@ -88,6 +89,7 @@ public class SubscribedFeedsProvider extends AbstractSyncableContentProvider { db.execSQL("CREATE TABLE feeds (" + "_id INTEGER PRIMARY KEY," + "_sync_account TEXT," + // From the sync source + "_sync_account_type TEXT," + // From the sync source "_sync_id TEXT," + // From the sync source "_sync_time TEXT," + // From the sync source "_sync_version TEXT," + // From the sync source @@ -106,8 +108,8 @@ public class SubscribedFeedsProvider extends AbstractSyncableContentProvider { "WHEN old._sync_id is not null " + "BEGIN " + "INSERT INTO _deleted_feeds " + - "(_sync_id, _sync_account, _sync_version) " + - "VALUES (old._sync_id, old._sync_account, " + + "(_sync_id, _sync_account, _sync_account_type, _sync_version) " + + "VALUES (old._sync_id, old._sync_account, old._sync_account_type, " + "old._sync_version);" + "END"); @@ -116,11 +118,22 @@ public class SubscribedFeedsProvider extends AbstractSyncableContentProvider { "_sync_id TEXT," + (isTemporary() ? "_sync_local_id INTEGER," : "") + // Used while syncing, "_sync_account TEXT," + + "_sync_account_type TEXT," + "_sync_mark INTEGER, " + // Used to filter out new rows "UNIQUE(_sync_id))"); } @Override + protected void onAccountsChanged(Account[] accountsArray) { + super.onAccountsChanged(accountsArray); + for (Account account : accountsArray) { + if (account.type.equals("com.google.GAIA")) { + ContentResolver.setSyncAutomatically(account, "subscribedfeeds", true); + } + } + } + + @Override protected void onDatabaseOpened(SQLiteDatabase db) { db.markTableSyncable("feeds", "_deleted_feeds"); } @@ -170,7 +183,8 @@ public class SubscribedFeedsProvider extends AbstractSyncableContentProvider { qb.setDistinct(true); qb.setProjectionMap(ACCOUNTS_PROJECTION_MAP); return qb.query(getDatabase(), projection, selection, selectionArgs, - SubscribedFeeds.Feeds._SYNC_ACCOUNT, null, sortOrder); + SubscribedFeeds.Feeds._SYNC_ACCOUNT_TYPE + "," + + SubscribedFeeds.Feeds._SYNC_ACCOUNT, null, sortOrder); case FEED_ID: qb.setTables(sFeedsTable); qb.appendWhere(sFeedsTable + "._id="); @@ -310,6 +324,8 @@ public class SubscribedFeedsProvider extends AbstractSyncableContentProvider { DatabaseUtils.cursorStringToContentValues(diffsCursor, SubscribedFeeds.Feeds._SYNC_ACCOUNT, mValues); DatabaseUtils.cursorStringToContentValues(diffsCursor, + SubscribedFeeds.Feeds._SYNC_ACCOUNT_TYPE, mValues); + DatabaseUtils.cursorStringToContentValues(diffsCursor, SubscribedFeeds.Feeds._SYNC_VERSION, mValues); db.replace(mDeletedTable, SubscribedFeeds.Feeds._SYNC_ID, mValues); } @@ -369,5 +385,7 @@ public class SubscribedFeedsProvider extends AbstractSyncableContentProvider { ACCOUNTS_PROJECTION_MAP = map; map.put(SubscribedFeeds.Accounts._COUNT, "COUNT(*) AS _count"); map.put(SubscribedFeeds.Accounts._SYNC_ACCOUNT, SubscribedFeeds.Accounts._SYNC_ACCOUNT); + map.put(SubscribedFeeds.Accounts._SYNC_ACCOUNT_TYPE, + SubscribedFeeds.Accounts._SYNC_ACCOUNT_TYPE); } } diff --git a/packages/TtsService/jni/android_tts_SynthProxy.cpp b/packages/TtsService/jni/android_tts_SynthProxy.cpp index 1bab717..071a90d 100644 --- a/packages/TtsService/jni/android_tts_SynthProxy.cpp +++ b/packages/TtsService/jni/android_tts_SynthProxy.cpp @@ -153,7 +153,7 @@ class SynthProxyJniStorage { AudioTrack* mAudioOut; AudioSystem::stream_type mStreamType; uint32_t mSampleRate; - AudioSystem::audio_format mAudFormat; + uint32_t mAudFormat; int mNbChannels; int8_t * mBuffer; size_t mBufferSize; @@ -200,7 +200,6 @@ class SynthProxyJniStorage { mSampleRate = rate; mAudFormat = format; mNbChannels = channel; - mStreamType = streamType; // retrieve system properties to ensure successful creation of the @@ -221,7 +220,8 @@ class SynthProxyJniStorage { if (minBufCount < 2) minBufCount = 2; int minFrameCount = (afFrameCount * rate * minBufCount)/afSampleRate; - mAudioOut = new AudioTrack(mStreamType, rate, format, channel, + mAudioOut = new AudioTrack(mStreamType, rate, format, + (channel == 2) ? AudioSystem::CHANNEL_OUT_STEREO : AudioSystem::CHANNEL_OUT_MONO, minFrameCount > 4096 ? minFrameCount : 4096, 0, 0, 0, 0); // not using an AudioTrack callback @@ -264,7 +264,7 @@ void prepAudioTrack(SynthProxyJniStorage* pJniData, AudioSystem::stream_type str * Directly speaks using AudioTrack or write to file */ static tts_callback_status ttsSynthDoneCB(void *& userdata, uint32_t rate, - AudioSystem::audio_format format, int channel, + uint32_t format, int channel, int8_t *&wav, size_t &bufferSize, tts_synth_status status) { //LOGV("ttsSynthDoneCallback: %d bytes", bufferSize); @@ -284,7 +284,7 @@ static tts_callback_status ttsSynthDoneCB(void *& userdata, uint32_t rate, } if (bufferSize > 0) { - prepAudioTrack(pJniData, pForAfter->streamType, rate, format, channel); + prepAudioTrack(pJniData, pForAfter->streamType, rate, (AudioSystem::audio_format)format, channel); if (pJniData->mAudioOut) { applyFilter((int16_t*)wav, bufferSize/2); pJniData->mAudioOut->write(wav, bufferSize); @@ -721,6 +721,27 @@ android_tts_SynthProxy_stop(JNIEnv *env, jobject thiz, jint jniData) } +static int +android_tts_SynthProxy_stopSync(JNIEnv *env, jobject thiz, jint jniData) +{ + int result = TTS_FAILURE; + + if (jniData == 0) { + LOGE("android_tts_SynthProxy_stop(): invalid JNI data"); + return result; + } + + // perform a regular stop + result = android_tts_SynthProxy_stop(env, thiz, jniData); + // but wait on the engine having released the engine mutex which protects + // the synthesizer resources. + engineMutex.lock(); + engineMutex.unlock(); + + return result; +} + + static jobjectArray android_tts_SynthProxy_getLanguage(JNIEnv *env, jobject thiz, jint jniData) { @@ -778,6 +799,10 @@ static JNINativeMethod gMethods[] = { "(I)I", (void*)android_tts_SynthProxy_stop }, + { "native_stopSync", + "(I)I", + (void*)android_tts_SynthProxy_stopSync + }, { "native_speak", "(ILjava/lang/String;I)I", (void*)android_tts_SynthProxy_speak diff --git a/packages/TtsService/src/android/tts/SynthProxy.java b/packages/TtsService/src/android/tts/SynthProxy.java index a0814aa..1d37ba0 100755 --- a/packages/TtsService/src/android/tts/SynthProxy.java +++ b/packages/TtsService/src/android/tts/SynthProxy.java @@ -40,7 +40,7 @@ public class SynthProxy { * Constructor; pass the location of the native TTS .so to use. */ public SynthProxy(String nativeSoLib) { - Log.e("TTS is loading", nativeSoLib); + Log.v(TtsService.SERVICE_TAG, "TTS is loading " + nativeSoLib); native_setup(new WeakReference<SynthProxy>(this), nativeSoLib); } @@ -52,6 +52,18 @@ public class SynthProxy { } /** + * Synchronous stop of the synthesizer. This method returns when the synth + * has completed the stop procedure and doesn't use any of the resources it + * was using while synthesizing. + * + * @return {@link android.speech.tts.TextToSpeech.SUCCESS} or + * {@link android.speech.tts.TextToSpeech.ERROR} + */ + public int stopSync() { + return native_stopSync(mJniData); + } + + /** * Synthesize speech and speak it directly using AudioTrack. */ public int speak(String text, int streamType) { @@ -156,6 +168,8 @@ public class SynthProxy { private native final int native_stop(int jniData); + private native final int native_stopSync(int jniData); + private native final int native_speak(int jniData, String text, int streamType); private native final int native_synthesizeToFile(int jniData, String text, String filename); diff --git a/packages/TtsService/src/android/tts/TtsService.java b/packages/TtsService/src/android/tts/TtsService.java index cd24727..217d3bb 100755 --- a/packages/TtsService/src/android/tts/TtsService.java +++ b/packages/TtsService/src/android/tts/TtsService.java @@ -34,6 +34,8 @@ import android.speech.tts.ITts.Stub; import android.speech.tts.ITtsCallback; import android.speech.tts.TextToSpeech; import android.util.Log; + +import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -120,6 +122,7 @@ public class TtsService extends Service implements OnCompletionListener { private static final String ACTION = "android.intent.action.START_TTS_SERVICE"; private static final String CATEGORY = "android.intent.category.TTS"; private static final String PKGNAME = "android.tts"; + protected static final String SERVICE_TAG = "TtsService"; private final RemoteCallbackList<ITtsCallback> mCallbacks = new RemoteCallbackList<ITtsCallback>(); @@ -138,6 +141,7 @@ public class TtsService extends Service implements OnCompletionListener { private ContentResolver mResolver; + // lock for the speech queue (mSpeechQueue) and the current speech item (mCurrentSpeechItem) private final ReentrantLock speechQueueLock = new ReentrantLock(); private final ReentrantLock synthesizerLock = new ReentrantLock(); @@ -145,7 +149,7 @@ public class TtsService extends Service implements OnCompletionListener { @Override public void onCreate() { super.onCreate(); - Log.i("TtsService", "TtsService.onCreate()"); + Log.v("TtsService", "TtsService.onCreate()"); mResolver = getContentResolver(); @@ -173,10 +177,7 @@ public class TtsService extends Service implements OnCompletionListener { public void onDestroy() { super.onDestroy(); - // TODO replace the call to stopAll() with a method to clear absolutely all upcoming - // uses of the native synth, including synthesis to a file, and delete files for which - // synthesis was not complete. - stopAll(""); + killAllUtterances(); // Don't hog the media player cleanUpPlayer(); @@ -188,6 +189,8 @@ public class TtsService extends Service implements OnCompletionListener { // Unregister all callbacks. mCallbacks.kill(); + + Log.v(SERVICE_TAG, "onDestroy() completed"); } @@ -279,7 +282,6 @@ public class TtsService extends Service implements OnCompletionListener { private int isLanguageAvailable(String lang, String country, String variant) { - //Log.v("TtsService", "TtsService.isLanguageAvailable(" + lang + ", " + country + ", " +variant+")"); int res = TextToSpeech.LANG_NOT_SUPPORTED; try { res = sNativeSynth.isLanguageAvailable(lang, country, variant); @@ -301,7 +303,7 @@ public class TtsService extends Service implements OnCompletionListener { private int setLanguage(String callingApp, String lang, String country, String variant) { - Log.v("TtsService", "TtsService.setLanguage(" + lang + ", " + country + ", " + variant + ")"); + Log.v(SERVICE_TAG, "TtsService.setLanguage(" + lang + ", " + country + ", " + variant + ")"); int res = TextToSpeech.ERROR; try { if (isDefaultEnforced()) { @@ -385,7 +387,7 @@ public class TtsService extends Service implements OnCompletionListener { * engines. */ private int speak(String callingApp, String text, int queueMode, ArrayList<String> params) { - Log.v("TtsService", "TTS service received " + text); + Log.v(SERVICE_TAG, "TTS service received " + text); if (queueMode == TextToSpeech.QUEUE_FLUSH) { stop(callingApp); } else if (queueMode == 2) { @@ -434,7 +436,7 @@ public class TtsService extends Service implements OnCompletionListener { speechQueueAvailable = speechQueueLock.tryLock(SPEECHQUEUELOCK_TIMEOUT, TimeUnit.MILLISECONDS); if (speechQueueAvailable) { - Log.i("TtsService", "Stopping"); + Log.i(SERVICE_TAG, "Stopping"); for (int i = mSpeechQueue.size() - 1; i > -1; i--){ if (mSpeechQueue.get(i).mCallingApp.equals(callingApp)){ mSpeechQueue.remove(i); @@ -461,10 +463,13 @@ public class TtsService extends Service implements OnCompletionListener { } else { result = TextToSpeech.SUCCESS; } - Log.i("TtsService", "Stopped"); + Log.i(SERVICE_TAG, "Stopped"); + } else { + Log.e(SERVICE_TAG, "TTS stop(): queue locked longer than expected"); + result = TextToSpeech.ERROR; } } catch (InterruptedException e) { - Log.e("TtsService", "TTS stop: tryLock interrupted"); + Log.e(SERVICE_TAG, "TTS stop: tryLock interrupted"); e.printStackTrace(); } finally { // This check is needed because finally will always run; even if the @@ -477,6 +482,63 @@ public class TtsService extends Service implements OnCompletionListener { } + /** + * Stops all speech output, both rendered to a file and directly spoken, and removes any + * utterances still in the queue globally. Files that were being written are deleted. + */ + @SuppressWarnings("finally") + private int killAllUtterances() { + int result = TextToSpeech.ERROR; + boolean speechQueueAvailable = false; + + try { + speechQueueAvailable = speechQueueLock.tryLock(SPEECHQUEUELOCK_TIMEOUT, + TimeUnit.MILLISECONDS); + if (speechQueueAvailable) { + // remove every single entry in the speech queue + mSpeechQueue.clear(); + + // clear the current speech item + if (mCurrentSpeechItem != null) { + result = sNativeSynth.stopSync(); + mKillList.put(mCurrentSpeechItem, true); + mIsSpeaking = false; + + // was the engine writing to a file? + if (mCurrentSpeechItem.mType == SpeechItem.TEXT_TO_FILE) { + // delete the file that was being written + if (mCurrentSpeechItem.mFilename != null) { + File tempFile = new File(mCurrentSpeechItem.mFilename); + Log.v(SERVICE_TAG, "Leaving behind " + mCurrentSpeechItem.mFilename); + if (tempFile.exists()) { + Log.v(SERVICE_TAG, "About to delete " + + mCurrentSpeechItem.mFilename); + if (tempFile.delete()) { + Log.v(SERVICE_TAG, "file successfully deleted"); + } + } + } + } + + mCurrentSpeechItem = null; + } + } else { + Log.e(SERVICE_TAG, "TTS killAllUtterances(): queue locked longer than expected"); + result = TextToSpeech.ERROR; + } + } catch (InterruptedException e) { + Log.e(SERVICE_TAG, "TTS killAllUtterances(): tryLock interrupted"); + result = TextToSpeech.ERROR; + } finally { + // This check is needed because finally will always run, even if the + // method returns somewhere in the try block. + if (speechQueueAvailable) { + speechQueueLock.unlock(); + } + return result; + } + } + /** * Stops all speech output and removes any utterances still in the queue globally, except @@ -516,10 +578,13 @@ public class TtsService extends Service implements OnCompletionListener { } else { result = TextToSpeech.SUCCESS; } - Log.i("TtsService", "Stopped all"); + Log.i(SERVICE_TAG, "Stopped all"); + } else { + Log.e(SERVICE_TAG, "TTS stopAll(): queue locked longer than expected"); + result = TextToSpeech.ERROR; } } catch (InterruptedException e) { - Log.e("TtsService", "TTS stopAll: tryLock interrupted"); + Log.e(SERVICE_TAG, "TTS stopAll: tryLock interrupted"); e.printStackTrace(); } finally { // This check is needed because finally will always run; even if the @@ -646,11 +711,11 @@ public class TtsService extends Service implements OnCompletionListener { sNativeSynth.speak(speechItem.mText, streamType); } catch (NullPointerException e) { // synth will become null during onDestroy() - Log.v("TtsService", " null synth, can't speak"); + Log.v(SERVICE_TAG, " null synth, can't speak"); } } } catch (InterruptedException e) { - Log.e("TtsService", "TTS speakInternalOnly(): tryLock interrupted"); + Log.e(SERVICE_TAG, "TTS speakInternalOnly(): tryLock interrupted"); e.printStackTrace(); } finally { // This check is needed because finally will always run; @@ -667,7 +732,7 @@ public class TtsService extends Service implements OnCompletionListener { } } Thread synth = (new Thread(new SynthThread())); - //synth.setPriority(Thread.MIN_PRIORITY); + synth.setPriority(Thread.MAX_PRIORITY); synth.start(); } @@ -676,7 +741,7 @@ public class TtsService extends Service implements OnCompletionListener { public void run() { boolean synthAvailable = false; String utteranceId = ""; - Log.i("TtsService", "Synthesizing to " + speechItem.mFilename); + Log.i(SERVICE_TAG, "Synthesizing to " + speechItem.mFilename); try { synthAvailable = synthesizerLock.tryLock(); if (!synthAvailable) { @@ -720,11 +785,11 @@ public class TtsService extends Service implements OnCompletionListener { sNativeSynth.synthesizeToFile(speechItem.mText, speechItem.mFilename); } catch (NullPointerException e) { // synth will become null during onDestroy() - Log.v("TtsService", " null synth, can't synthesize to file"); + Log.v(SERVICE_TAG, " null synth, can't synthesize to file"); } } } catch (InterruptedException e) { - Log.e("TtsService", "TTS synthToFileInternalOnly(): tryLock interrupted"); + Log.e(SERVICE_TAG, "TTS synthToFileInternalOnly(): tryLock interrupted"); e.printStackTrace(); } finally { // This check is needed because finally will always run; @@ -741,7 +806,7 @@ public class TtsService extends Service implements OnCompletionListener { } } Thread synth = (new Thread(new SynthThread())); - //synth.setPriority(Thread.MIN_PRIORITY); + synth.setPriority(Thread.MAX_PRIORITY); synth.start(); } @@ -769,7 +834,7 @@ public class TtsService extends Service implements OnCompletionListener { if (cb == null){ return; } - Log.i("TtsService", "TTS callback: dispatch started"); + Log.v(SERVICE_TAG, "TTS callback: dispatch started"); // Broadcast to all clients the new value. final int N = mCallbacks.beginBroadcast(); try { @@ -779,7 +844,7 @@ public class TtsService extends Service implements OnCompletionListener { // the dead object for us. } mCallbacks.finishBroadcast(); - Log.i("TtsService", "TTS callback: dispatch completed to " + N); + Log.v(SERVICE_TAG, "TTS callback: dispatch completed to " + N); } private SpeechItem splitCurrentTextIfNeeded(SpeechItem currentSpeechItem){ @@ -816,11 +881,12 @@ public class TtsService extends Service implements OnCompletionListener { speechQueueAvailable = speechQueueLock.tryLock(SPEECHQUEUELOCK_TIMEOUT, TimeUnit.MILLISECONDS); if (!speechQueueAvailable) { - Log.e("TtsService", "processSpeechQueue - Speech queue is unavailable."); + Log.e(SERVICE_TAG, "processSpeechQueue - Speech queue is unavailable."); return; } if (mSpeechQueue.size() < 1) { mIsSpeaking = false; + mKillList.clear(); broadcastTtsQueueProcessingCompleted(); return; } @@ -830,7 +896,7 @@ public class TtsService extends Service implements OnCompletionListener { SoundResource sr = getSoundResource(mCurrentSpeechItem); // Synth speech as needed - synthesizer should call // processSpeechQueue to continue running the queue - Log.i("TtsService", "TTS processing: " + mCurrentSpeechItem.mText); + Log.v(SERVICE_TAG, "TTS processing: " + mCurrentSpeechItem.mText); if (sr == null) { if (mCurrentSpeechItem.mType == SpeechItem.TEXT) { mCurrentSpeechItem = splitCurrentTextIfNeeded(mCurrentSpeechItem); @@ -886,7 +952,7 @@ public class TtsService extends Service implements OnCompletionListener { mSpeechQueue.remove(0); } } catch (InterruptedException e) { - Log.e("TtsService", "TTS processSpeechQueue: tryLock interrupted"); + Log.e(SERVICE_TAG, "TTS processSpeechQueue: tryLock interrupted"); e.printStackTrace(); } finally { // This check is needed because finally will always run; even if the diff --git a/packages/VpnServices/res/values-cs/strings.xml b/packages/VpnServices/res/values-cs/strings.xml index 58e211d..5f3522d 100644 --- a/packages/VpnServices/res/values-cs/strings.xml +++ b/packages/VpnServices/res/values-cs/strings.xml @@ -15,8 +15,11 @@ --> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="app_label" msgid="4589592829302498102">"Služby VPN"</string> - <string name="vpn_notification_title_connected" msgid="2567196609405266775">"Síť VPN %s připojena"</string> - <string name="vpn_notification_title_disconnected" msgid="3564361788336568244">"Síť VPN %s odpojena"</string> - <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"Dotykem se znovu připojíte k síti VPN."</string> + <string name="app_label">"Služby VPN"</string> + <!-- no translation found for vpn_notification_title_connected (2567196609405266775) --> + <skip /> + <!-- no translation found for vpn_notification_title_disconnected (3564361788336568244) --> + <skip /> + <!-- no translation found for vpn_notification_hint_disconnected (1952209867082269429) --> + <skip /> </resources> diff --git a/packages/VpnServices/res/values-de/strings.xml b/packages/VpnServices/res/values-de/strings.xml index 23558bb..93fa474 100644 --- a/packages/VpnServices/res/values-de/strings.xml +++ b/packages/VpnServices/res/values-de/strings.xml @@ -15,8 +15,11 @@ --> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="app_label" msgid="4589592829302498102">"VPN-Dienste"</string> - <string name="vpn_notification_title_connected" msgid="2567196609405266775">"VPN \"%s\" verbunden"</string> - <string name="vpn_notification_title_disconnected" msgid="3564361788336568244">"VPN \"%s \" getrennt"</string> - <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"Zur Wiederherstellung der Verbindung mit einem VPN berühren"</string> + <string name="app_label">"VPN-Dienste"</string> + <!-- no translation found for vpn_notification_title_connected (2567196609405266775) --> + <skip /> + <!-- no translation found for vpn_notification_title_disconnected (3564361788336568244) --> + <skip /> + <!-- no translation found for vpn_notification_hint_disconnected (1952209867082269429) --> + <skip /> </resources> diff --git a/packages/VpnServices/res/values-es/strings.xml b/packages/VpnServices/res/values-es/strings.xml index bc7e536..bb4f348 100644 --- a/packages/VpnServices/res/values-es/strings.xml +++ b/packages/VpnServices/res/values-es/strings.xml @@ -15,8 +15,11 @@ --> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="app_label" msgid="4589592829302498102">"Servicios VPN"</string> - <string name="vpn_notification_title_connected" msgid="2567196609405266775">"VPN %s conectada"</string> - <string name="vpn_notification_title_disconnected" msgid="3564361788336568244">"VPN %s desconectada"</string> - <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"Toca para volver a conectarte a una red VPN."</string> + <string name="app_label">"Servicios VPN"</string> + <!-- no translation found for vpn_notification_title_connected (2567196609405266775) --> + <skip /> + <!-- no translation found for vpn_notification_title_disconnected (3564361788336568244) --> + <skip /> + <!-- no translation found for vpn_notification_hint_disconnected (1952209867082269429) --> + <skip /> </resources> diff --git a/packages/VpnServices/res/values-fr/strings.xml b/packages/VpnServices/res/values-fr/strings.xml index 5db5050..4395d03 100644 --- a/packages/VpnServices/res/values-fr/strings.xml +++ b/packages/VpnServices/res/values-fr/strings.xml @@ -15,8 +15,11 @@ --> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="app_label" msgid="4589592829302498102">"Services VPN"</string> - <string name="vpn_notification_title_connected" msgid="2567196609405266775">"VPN %s connecté"</string> - <string name="vpn_notification_title_disconnected" msgid="3564361788336568244">"VPN %s déconnecté"</string> - <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"Touchez l\'écran pour vous reconnecter à un VPN."</string> + <string name="app_label">"Services VPN"</string> + <!-- no translation found for vpn_notification_title_connected (2567196609405266775) --> + <skip /> + <!-- no translation found for vpn_notification_title_disconnected (3564361788336568244) --> + <skip /> + <!-- no translation found for vpn_notification_hint_disconnected (1952209867082269429) --> + <skip /> </resources> diff --git a/packages/VpnServices/res/values-it/strings.xml b/packages/VpnServices/res/values-it/strings.xml index cc2a4eb..76e0214 100644 --- a/packages/VpnServices/res/values-it/strings.xml +++ b/packages/VpnServices/res/values-it/strings.xml @@ -15,8 +15,11 @@ --> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="app_label" msgid="4589592829302498102">"Servizi VPN"</string> - <string name="vpn_notification_title_connected" msgid="2567196609405266775">"VPN %s collegata"</string> - <string name="vpn_notification_title_disconnected" msgid="3564361788336568244">"VPN %s scollegata"</string> - <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"Tocca per riconnetterti a una rete VPN."</string> + <string name="app_label">"Servizi VPN"</string> + <!-- no translation found for vpn_notification_title_connected (2567196609405266775) --> + <skip /> + <!-- no translation found for vpn_notification_title_disconnected (3564361788336568244) --> + <skip /> + <!-- no translation found for vpn_notification_hint_disconnected (1952209867082269429) --> + <skip /> </resources> diff --git a/packages/VpnServices/res/values-ja/strings.xml b/packages/VpnServices/res/values-ja/strings.xml deleted file mode 100644 index 1158347..0000000 --- a/packages/VpnServices/res/values-ja/strings.xml +++ /dev/null @@ -1,22 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2009 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="app_label" msgid="4589592829302498102">"VPNサービス"</string> - <string name="vpn_notification_title_connected" msgid="2567196609405266775">"%s VPNが接続されました"</string> - <string name="vpn_notification_title_disconnected" msgid="3564361788336568244">"%s VPNが切断されました"</string> - <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"タップしてVPNに再接続してください。"</string> -</resources> diff --git a/packages/VpnServices/res/values-nl/strings.xml b/packages/VpnServices/res/values-nl/strings.xml index 359cfe9..9a50f3b 100644 --- a/packages/VpnServices/res/values-nl/strings.xml +++ b/packages/VpnServices/res/values-nl/strings.xml @@ -15,8 +15,11 @@ --> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="app_label" msgid="4589592829302498102">"VPN-services"</string> - <string name="vpn_notification_title_connected" msgid="2567196609405266775">"%s VPN verbonden"</string> - <string name="vpn_notification_title_disconnected" msgid="3564361788336568244">"%s VPN-verbinding verbroken"</string> - <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"Raak aan om opnieuw verbinding te maken met een VPN."</string> + <string name="app_label">"VPN-services"</string> + <!-- no translation found for vpn_notification_title_connected (2567196609405266775) --> + <skip /> + <!-- no translation found for vpn_notification_title_disconnected (3564361788336568244) --> + <skip /> + <!-- no translation found for vpn_notification_hint_disconnected (1952209867082269429) --> + <skip /> </resources> diff --git a/packages/VpnServices/res/values-pl/strings.xml b/packages/VpnServices/res/values-pl/strings.xml index 17d1dab..d2e8c60 100644 --- a/packages/VpnServices/res/values-pl/strings.xml +++ b/packages/VpnServices/res/values-pl/strings.xml @@ -15,8 +15,11 @@ --> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="app_label" msgid="4589592829302498102">"Usługi VPN"</string> - <string name="vpn_notification_title_connected" msgid="2567196609405266775">"Połączono z siecią VPN %s"</string> - <string name="vpn_notification_title_disconnected" msgid="3564361788336568244">"Rozłączono z siecią VPN %s"</string> - <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"Dotknij, aby ponownie połączyć się z siecią VPN."</string> + <string name="app_label">"Usługi VPN"</string> + <!-- no translation found for vpn_notification_title_connected (2567196609405266775) --> + <skip /> + <!-- no translation found for vpn_notification_title_disconnected (3564361788336568244) --> + <skip /> + <!-- no translation found for vpn_notification_hint_disconnected (1952209867082269429) --> + <skip /> </resources> diff --git a/packages/VpnServices/res/values-zh-rTW/strings.xml b/packages/VpnServices/res/values-zh-rTW/strings.xml index ad8eddf..021077b 100644 --- a/packages/VpnServices/res/values-zh-rTW/strings.xml +++ b/packages/VpnServices/res/values-zh-rTW/strings.xml @@ -15,8 +15,11 @@ --> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="app_label" msgid="4589592829302498102">"VPN 服務"</string> - <string name="vpn_notification_title_connected" msgid="2567196609405266775">"%s VPN 已連線"</string> - <string name="vpn_notification_title_disconnected" msgid="3564361788336568244">"%s VPN 已中斷連線"</string> - <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"輕觸即可重新連線至 VPN。"</string> + <string name="app_label">"VPN 服務"</string> + <!-- no translation found for vpn_notification_title_connected (2567196609405266775) --> + <skip /> + <!-- no translation found for vpn_notification_title_disconnected (3564361788336568244) --> + <skip /> + <!-- no translation found for vpn_notification_hint_disconnected (1952209867082269429) --> + <skip /> </resources> diff --git a/packages/VpnServices/res/values/strings.xml b/packages/VpnServices/res/values/strings.xml index 074655e..d82f52a 100755 --- a/packages/VpnServices/res/values/strings.xml +++ b/packages/VpnServices/res/values/strings.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="utf-8"?> -<resources> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <!-- Title for the VPN Services activity. --> <string name="app_label">VPN Services</string> - <string name="vpn_notification_title_connected">%s VPN connected</string> - <string name="vpn_notification_title_disconnected">%s VPN disconnected</string> + <string name="vpn_notification_title_connected"><xliff:g id="profilename">%s</xliff:g> VPN connected</string> + <string name="vpn_notification_title_disconnected"><xliff:g id="profilename">%s</xliff:g> VPN disconnected</string> <string name="vpn_notification_hint_disconnected">Touch to reconnect to a VPN.</string> </resources> diff --git a/packages/VpnServices/src/com/android/server/vpn/VpnService.java b/packages/VpnServices/src/com/android/server/vpn/VpnService.java index e3ac996..53167f6 100644 --- a/packages/VpnServices/src/com/android/server/vpn/VpnService.java +++ b/packages/VpnServices/src/com/android/server/vpn/VpnService.java @@ -56,10 +56,6 @@ abstract class VpnService<E extends VpnProfile> implements Serializable { private static final String REMOTE_IP = "net.ipremote"; private static final String DNS_DOMAIN_SUFFICES = "net.dns.search"; - private static final int CHALLENGE_ERROR_CODE = 5; - private static final int REMOTE_HUNG_UP_ERROR_CODE = 7; - private static final int AUTH_ERROR_CODE = 51; - private final String TAG = VpnService.class.getSimpleName(); // FIXME: profile is only needed in connecting phase, so we can just save @@ -202,7 +198,7 @@ abstract class VpnService<E extends VpnProfile> implements Serializable { private void waitUntilConnectedOrTimedout() throws IOException { sleep(2000); // 2 seconds - for (int i = 0; i < 60; i++) { + for (int i = 0; i < 80; i++) { if (mState != VpnState.CONNECTING) { break; } else if (VPN_IS_UP.equals( @@ -464,22 +460,8 @@ abstract class VpnService<E extends VpnProfile> implements Serializable { synchronized int getSocketError() { for (DaemonProxy s : mDaemonList) { - switch (getResultFromSocket(s)) { - case 0: - continue; - - case AUTH_ERROR_CODE: - return VpnManager.VPN_ERROR_AUTH; - - case CHALLENGE_ERROR_CODE: - return VpnManager.VPN_ERROR_CHALLENGE; - - case REMOTE_HUNG_UP_ERROR_CODE: - return VpnManager.VPN_ERROR_REMOTE_HUNG_UP; - - default: - return VpnManager.VPN_ERROR_CONNECTION_FAILED; - } + int errCode = getResultFromSocket(s); + if (errCode != 0) return errCode; } return 0; } diff --git a/packages/VpnServices/src/com/android/server/vpn/VpnServiceBinder.java b/packages/VpnServices/src/com/android/server/vpn/VpnServiceBinder.java index 4892a7b..e5be847 100644 --- a/packages/VpnServices/src/com/android/server/vpn/VpnServiceBinder.java +++ b/packages/VpnServices/src/com/android/server/vpn/VpnServiceBinder.java @@ -91,7 +91,8 @@ public class VpnServiceBinder extends Service { void removeStates() { try { - new File(STATES_FILE_PATH).delete(); + File f = new File(STATES_FILE_PATH); + if (f.exists()) f.delete(); } catch (Throwable e) { if (DBG) Log.d("VpnServiceBinder", " remove states: " + e); } |