Merge "Fix bug 2523989"
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 1c980e3..fa6abec 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -3908,16 +3908,16 @@
         }
     }
 
-    final void applyConfigurationToResourcesLocked(Configuration config) {
+    final boolean applyConfigurationToResourcesLocked(Configuration config) {
         if (mResConfiguration == null) {
             mResConfiguration = new Configuration();
         }
         if (!mResConfiguration.isOtherSeqNewer(config)) {
             if (DEBUG_CONFIGURATION) Log.v(TAG, "Skipping new config: curSeq="
                     + mResConfiguration.seq + ", newSeq=" + config.seq);
-            return;
+            return false;
         }
-        mResConfiguration.updateFrom(config);
+        int changes = mResConfiguration.updateFrom(config);
         DisplayMetrics dm = getDisplayMetricsLocked(true);
 
         // set it for java, this also affects newly created Resources
@@ -3948,6 +3948,8 @@
                 it.remove();
             }
         }
+        
+        return changes != 0;
     }
     
     final void handleConfigurationChanged(Configuration config) {
@@ -4522,17 +4524,20 @@
         ViewRoot.addConfigCallback(new ComponentCallbacks() {
             public void onConfigurationChanged(Configuration newConfig) {
                 synchronized (mPackages) {
-                    if (mPendingConfiguration == null ||
-                            mPendingConfiguration.isOtherSeqNewer(newConfig)) {
-                        mPendingConfiguration = newConfig;
-                        
-                        // We need to apply this change to the resources
-                        // immediately, because upon returning the view
-                        // hierarchy will be informed about it.
-                        applyConfigurationToResourcesLocked(newConfig);
+                    // We need to apply this change to the resources
+                    // immediately, because upon returning the view
+                    // hierarchy will be informed about it.
+                    if (applyConfigurationToResourcesLocked(newConfig)) {
+                        // This actually changed the resources!  Tell
+                        // everyone about it.
+                        if (mPendingConfiguration == null ||
+                                mPendingConfiguration.isOtherSeqNewer(newConfig)) {
+                            mPendingConfiguration = newConfig;
+                            
+                            queueOrSendMessage(H.CONFIGURATION_CHANGED, newConfig);
+                        }
                     }
                 }
-                queueOrSendMessage(H.CONFIGURATION_CHANGED, newConfig);
             }
             public void onLowMemory() {
             }
diff --git a/core/jni/android_database_SQLiteDatabase.cpp b/core/jni/android_database_SQLiteDatabase.cpp
index 4e8d05b..36234a9 100644
--- a/core/jni/android_database_SQLiteDatabase.cpp
+++ b/core/jni/android_database_SQLiteDatabase.cpp
@@ -72,8 +72,9 @@
 }
 
 static void sqlLogger(void *databaseName, int iErrCode, const char *zMsg) {
-    LOGI("sqlite returned: database = %s, error code = %d, msg = %s\n",
-            (char *)databaseName, iErrCode, zMsg);
+    // skip printing this message if it is due to certain types of errors
+    if (iErrCode == SQLITE_CONSTRAINT) return;
+    LOGI("sqlite returned: error code = %d, msg = %s\n", iErrCode, zMsg);
 }
 
 // register the logging func on sqlite. needs to be done BEFORE any sqlite3 func is called.
diff --git a/include/tts/TtsEngine.h b/include/tts/TtsEngine.h
index 28b0d2f..998e353 100644
--- a/include/tts/TtsEngine.h
+++ b/include/tts/TtsEngine.h
@@ -26,6 +26,12 @@
 
 namespace android {
 
+#define ANDROID_TTS_ENGINE_PROPERTY_CONFIG "engineConfig"
+#define ANDROID_TTS_ENGINE_PROPERTY_PITCH  "pitch"
+#define ANDROID_TTS_ENGINE_PROPERTY_RATE   "rate"
+#define ANDROID_TTS_ENGINE_PROPERTY_VOLUME "volume"
+
+
 enum tts_synth_status {
     TTS_SYNTH_DONE              = 0,
     TTS_SYNTH_PENDING           = 1
@@ -85,7 +91,7 @@
     // Initialize the TTS engine and returns whether initialization succeeded.
     // @param synthDoneCBPtr synthesis callback function pointer
     // @return TTS_SUCCESS, or TTS_FAILURE
-    virtual tts_result init(synthDoneCB_t synthDoneCBPtr);
+    virtual tts_result init(synthDoneCB_t synthDoneCBPtr, const char *engineConfig);
 
     // Shut down the TTS engine and releases all associated resources.
     // @return TTS_SUCCESS, or TTS_FAILURE
@@ -122,7 +128,7 @@
     // @param variant pointer to the variant code
     // @return TTS_SUCCESS, or TTS_FAILURE
     virtual tts_result loadLanguage(const char *lang, const char *country, const char *variant);
-    
+
     // Load the resources associated with the specified language, country and Locale variant.
     // The loaded language will only be used once a call to setLanguageFromLocale() with the same
     // language value is issued. Language and country values are coded according to the ISO three
@@ -220,19 +226,6 @@
     virtual tts_result synthesizeText(const char *text, int8_t *buffer,
             size_t bufferSize, void *userdata);
 
-    // Synthesize IPA text.
-    // As the synthesis is performed, the engine invokes the callback to notify
-    // the TTS framework that it has filled the given buffer, and indicates how
-    // many bytes it wrote. The callback is called repeatedly until the engine
-    // has generated all the audio data corresponding to the IPA data.
-    // @param ipa      the IPA data to synthesize
-    // @param userdata  pointer to be returned when the call is invoked
-    // @param buffer    the location where the synthesized data must be written
-    // @param bufferSize the number of bytes that can be written in buffer
-    // @return TTS_FEATURE_UNSUPPORTED if IPA is not supported,
-    //         otherwise TTS_SUCCESS or TTS_FAILURE
-    virtual tts_result synthesizeIpa(const char *ipa, int8_t *buffer,
-            size_t bufferSize, void *userdata);
 };
 
 } // namespace android
diff --git a/media/libstagefright/omx/tests/OMXHarness.cpp b/media/libstagefright/omx/tests/OMXHarness.cpp
index c05d90a..fcf506d 100644
--- a/media/libstagefright/omx/tests/OMXHarness.cpp
+++ b/media/libstagefright/omx/tests/OMXHarness.cpp
@@ -595,6 +595,9 @@
 
     static const int32_t kNumIterations = 5000;
 
+    // We are always going to seek beyond EOS in the first iteration (i == 0)
+    // followed by a linear read for the second iteration (i == 1).
+    // After that it's all random.
     for (int32_t i = 0; i < kNumIterations; ++i) {
         int64_t requestedSeekTimeUs;
         int64_t actualSeekTimeUs;
@@ -602,14 +605,14 @@
 
         double r = uniform_rand();
 
-        if (i > 0 && r < 0.5) {
+        if ((i == 1) || (i > 0 && r < 0.5)) {
             // 50% chance of just continuing to decode from last position.
 
             requestedSeekTimeUs = -1;
 
             LOGI("requesting linear read");
         } else {
-            if (i > 0 && r < 0.55) {
+            if (i == 0 || r < 0.55) {
                 // 5% chance of seeking beyond end of stream.
 
                 requestedSeekTimeUs = durationUs;
@@ -674,7 +677,15 @@
                 buffer = NULL;
             }
         } else if (actualSeekTimeUs < 0) {
-            CHECK(err != OK);
+            EXPECT(err != OK,
+                   "We attempted to seek beyond EOS and expected "
+                   "ERROR_END_OF_STREAM to be returned, but instead "
+                   "we got a valid buffer.");
+            EXPECT(err == ERROR_END_OF_STREAM,
+                   "We attempted to seek beyond EOS and expected "
+                   "ERROR_END_OF_STREAM to be returned, but instead "
+                   "we found some other error.");
+            CHECK_EQ(err, ERROR_END_OF_STREAM);
             CHECK_EQ(buffer, NULL);
         } else {
             EXPECT(err == OK,
diff --git a/packages/TtsService/jni/android_tts_SynthProxy.cpp b/packages/TtsService/jni/android_tts_SynthProxy.cpp
index b7acd96..1d69361 100644
--- a/packages/TtsService/jni/android_tts_SynthProxy.cpp
+++ b/packages/TtsService/jni/android_tts_SynthProxy.cpp
@@ -383,7 +383,7 @@
 // ----------------------------------------------------------------------------
 static int
 android_tts_SynthProxy_native_setup(JNIEnv *env, jobject thiz,
-        jobject weak_this, jstring nativeSoLib)
+        jobject weak_this, jstring nativeSoLib, jstring engConfig)
 {
     int result = TTS_FAILURE;
 
@@ -395,6 +395,7 @@
             DEFAULT_TTS_STREAM_TYPE, DEFAULT_TTS_RATE, DEFAULT_TTS_FORMAT, DEFAULT_TTS_NB_CHANNELS);
 
     const char *nativeSoLibNativeString =  env->GetStringUTFChars(nativeSoLib, 0);
+    const char *engConfigString = env->GetStringUTFChars(engConfig, 0);
 
     void *engine_lib_handle = dlopen(nativeSoLibNativeString,
             RTLD_NOW | RTLD_LOCAL);
@@ -409,7 +410,7 @@
 
         if (pJniStorage->mNativeSynthInterface) {
             Mutex::Autolock l(engineMutex);
-            pJniStorage->mNativeSynthInterface->init(ttsSynthDoneCB);
+            pJniStorage->mNativeSynthInterface->init(ttsSynthDoneCB, engConfigString);
         }
 
         result = TTS_SUCCESS;
@@ -422,6 +423,7 @@
     env->SetIntField(thiz, javaTTSFields.synthProxyFieldJniData, (int)pJniStorage);
 
     env->ReleaseStringUTFChars(nativeSoLib, nativeSoLibNativeString);
+    env->ReleaseStringUTFChars(engConfig, engConfigString);
 
     return result;
 }
@@ -482,6 +484,29 @@
     return result;
 }
 
+static int
+android_tts_SynthProxy_setConfig(JNIEnv *env, jobject thiz, jint jniData, jstring engineConfig)
+{
+    int result = TTS_FAILURE;
+
+    if (jniData == 0) {
+        LOGE("android_tts_SynthProxy_setConfig(): invalid JNI data");
+        return result;
+    }
+
+    Mutex::Autolock l(engineMutex);
+
+    SynthProxyJniStorage* pSynthData = (SynthProxyJniStorage*)jniData;
+    const char *engineConfigNativeString = env->GetStringUTFChars(engineConfig, 0);
+
+    if (pSynthData->mNativeSynthInterface) {
+        result = pSynthData->mNativeSynthInterface->setProperty(ANDROID_TTS_ENGINE_PROPERTY_CONFIG,
+                engineConfigNativeString, strlen(engineConfigNativeString));
+    }
+    env->ReleaseStringUTFChars(engineConfig, engineConfigNativeString);
+
+    return result;
+}
 
 static int
 android_tts_SynthProxy_setLanguage(JNIEnv *env, jobject thiz, jint jniData,
@@ -867,6 +892,10 @@
         "(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
         (void*)android_tts_SynthProxy_isLanguageAvailable
     },
+    {   "native_setConfig",
+            "(ILjava/lang/String;)I",
+            (void*)android_tts_SynthProxy_setConfig
+    },
     {   "native_setLanguage",
         "(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
         (void*)android_tts_SynthProxy_setLanguage
@@ -896,7 +925,7 @@
         (void*)android_tts_SynthProxy_shutdown
     },
     {   "native_setup",
-        "(Ljava/lang/Object;Ljava/lang/String;)I",
+        "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;)I",
         (void*)android_tts_SynthProxy_native_setup
     },
     {   "native_setLowShelf",
diff --git a/packages/TtsService/src/android/tts/SynthProxy.java b/packages/TtsService/src/android/tts/SynthProxy.java
index 5f283e1..2a0bbeb 100755
--- a/packages/TtsService/src/android/tts/SynthProxy.java
+++ b/packages/TtsService/src/android/tts/SynthProxy.java
@@ -51,7 +51,7 @@
     public SynthProxy(String nativeSoLib, String engineConfig) {
         boolean applyFilter = nativeSoLib.toLowerCase().contains("pico");
         Log.v(TtsService.SERVICE_TAG, "About to load "+ nativeSoLib + ", applyFilter="+applyFilter);
-        native_setup(new WeakReference<SynthProxy>(this), nativeSoLib);
+        native_setup(new WeakReference<SynthProxy>(this), nativeSoLib, engineConfig);
         native_setLowShelf(applyFilter, PICO_FILTER_GAIN, PICO_FILTER_LOWSHELF_ATTENUATION,
                 PICO_FILTER_TRANSITION_FREQ, PICO_FILTER_SHELF_SLOPE);
     }
@@ -105,10 +105,10 @@
     }
 
     /**
-     * Sets the engine configuration.
+     * Updates the engine configuration.
      */
     public int setConfig(String engineConfig) {
-        return android.speech.tts.TextToSpeech.SUCCESS;
+        return native_setConfig(engineConfig);
     }
 
     /**
@@ -180,7 +180,8 @@
      */
     private int mJniData = 0;
 
-    private native final int native_setup(Object weak_this, String nativeSoLib);
+    private native final int native_setup(Object weak_this, String nativeSoLib,
+            String engineConfig);
 
     private native final int native_setLowShelf(boolean applyFilter, float filterGain,
             float attenuationInDb, float freqInHz, float slope);
@@ -204,6 +205,8 @@
     private native final int native_loadLanguage(int jniData, String language, String country,
             String variant);
 
+    private native final int native_setConfig(String engineConfig);
+
     private native final int native_setSpeechRate(int jniData, int speechRate);
 
     private native final int native_setPitch(int jniData, int speechRate);
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 4eb529c..12666927 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -308,13 +308,17 @@
                         }
                     } catch (Exception e) {
                         Slog.e(TAG, "Error configuring interface " + intf + ", :" + e);
+                        try {
+                            nwService.stopAccessPoint();
+                        } catch (Exception ee) {
+                            Slog.e(TAG, "Could not stop AP, :" + ee);
+                        }
                         setWifiApEnabledState(WIFI_AP_STATE_FAILED, 0, DriverAction.DRIVER_UNLOAD);
                         return;
                     }
 
                     if(mCm.tether(intf) != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
                         Slog.e(TAG, "Error tethering "+intf);
-                        setWifiApEnabledState(WIFI_AP_STATE_FAILED, 0, DriverAction.DRIVER_UNLOAD);
                     }
                     break;
                 }
diff --git a/tools/aapt/Bundle.h b/tools/aapt/Bundle.h
index 08530a0..c8b6837 100644
--- a/tools/aapt/Bundle.h
+++ b/tools/aapt/Bundle.h
@@ -37,12 +37,12 @@
           mForce(false), mGrayscaleTolerance(0), mMakePackageDirs(false),
           mUpdate(false), mExtending(false),
           mRequireLocalization(false), mPseudolocalize(false),
-          mUTF8(false), mEncodingSpecified(false), mValues(false),
+          mWantUTF16(false), mValues(false),
           mCompressionMethod(0), mOutputAPKFile(NULL),
           mManifestPackageNameOverride(NULL), mInstrumentationPackageNameOverride(NULL),
           mAutoAddOverlay(false), mAssetSourceDir(NULL), mProguardFile(NULL),
           mAndroidManifestFile(NULL), mPublicOutputFile(NULL),
-          mRClassDir(NULL), mResourceIntermediatesDir(NULL),
+          mRClassDir(NULL), mResourceIntermediatesDir(NULL), mManifestMinSdkVersion(NULL),
           mMinSdkVersion(NULL), mTargetSdkVersion(NULL), mMaxSdkVersion(NULL),
           mVersionCode(NULL), mVersionName(NULL), mCustomPackage(NULL),
           mArgc(0), mArgv(NULL)
@@ -77,10 +77,8 @@
     void setRequireLocalization(bool val) { mRequireLocalization = val; }
     bool getPseudolocalize(void) const { return mPseudolocalize; }
     void setPseudolocalize(bool val) { mPseudolocalize = val; }
-    bool getUTF8(void) const { return mUTF8; }
-    void setUTF8(bool val) { mUTF8 = val; }
-    bool getEncodingSpecified(void) const { return mEncodingSpecified; }
-    void setEncodingSpecified(bool val) { mEncodingSpecified = val; }
+    bool getWantUTF16(void) const { return mWantUTF16; }
+    void setWantUTF16(bool val) { mWantUTF16 = val; }
     bool getValues(void) const { return mValues; }
     void setValues(bool val) { mValues = val; }
     int getCompressionMethod(void) const { return mCompressionMethod; }
@@ -122,13 +120,10 @@
     const android::Vector<const char*>& getNoCompressExtensions() const { return mNoCompressExtensions; }
     void addNoCompressExtension(const char* ext) { mNoCompressExtensions.add(ext); }
 
+    const char*  getManifestMinSdkVersion() const { return mManifestMinSdkVersion; }
+    void setManifestMinSdkVersion(const char*  val) { mManifestMinSdkVersion = val; }
     const char*  getMinSdkVersion() const { return mMinSdkVersion; }
-    void setMinSdkVersion(const char*  val) {
-        mMinSdkVersion = val;
-        if (!mEncodingSpecified) {
-            setUTF8(isUTF8Available());
-        }
-    }
+    void setMinSdkVersion(const char*  val) { mMinSdkVersion = val; }
     const char*  getTargetSdkVersion() const { return mTargetSdkVersion; }
     void setTargetSdkVersion(const char*  val) { mTargetSdkVersion = val; }
     const char*  getMaxSdkVersion() const { return mMaxSdkVersion; }
@@ -167,6 +162,34 @@
     void setPackageCount(int val) { mPackageCount = val; }
 #endif
 
+    /* UTF-8 is only available on APIs 7 or above or
+     * SDK levels that have code names.
+     */
+    bool isUTF8Available() {
+        /* If the application specifies a minSdkVersion in the manifest
+         * then use that. Otherwise, check what the user specified on
+         * the command line. If neither, it's not available since
+         * the minimum SDK version is assumed to be 1.
+         */
+        const char *minVer;
+        if (mManifestMinSdkVersion != NULL) {
+            minVer = mManifestMinSdkVersion;
+        } else if (mMinSdkVersion != NULL) {
+            minVer = mMinSdkVersion;
+        } else {
+            return false;
+        }
+
+        char *end;
+        int minSdkNum = (int)strtol(minVer, &end, 0);
+        if (*end == '\0') {
+            if (minSdkNum < 7) {
+                return false;
+            }
+        }
+        return true;
+    }
+
 private:
     /* commands & modifiers */
     Command     mCmd;
@@ -179,8 +202,7 @@
     bool        mExtending;
     bool        mRequireLocalization;
     bool        mPseudolocalize;
-    bool        mUTF8;
-    bool        mEncodingSpecified;
+    bool        mWantUTF16;
     bool        mValues;
     int         mCompressionMethod;
     bool        mJunkPath;
@@ -200,6 +222,7 @@
     android::Vector<const char*> mNoCompressExtensions;
     android::Vector<const char*> mResourceSourceDirs;
 
+    const char* mManifestMinSdkVersion;
     const char* mMinSdkVersion;
     const char* mTargetSdkVersion;
     const char* mMaxSdkVersion;
@@ -216,19 +239,6 @@
     int         mPackageCount;
 #endif
 
-    /* UTF-8 is only available on APIs 7 or above or
-     * SDK levels that have code names.
-     */
-    bool isUTF8Available() {
-        char *end;
-        int minSdkNum = (int)strtol(mMinSdkVersion, &end, 0);
-        if (*end == '\0') {
-            if (minSdkNum < 7) {
-                return false;
-            }
-        }
-        return true;
-    }
 };
 
 #endif // __BUNDLE_H
diff --git a/tools/aapt/Main.cpp b/tools/aapt/Main.cpp
index dd98c85..b0c6e39 100644
--- a/tools/aapt/Main.cpp
+++ b/tools/aapt/Main.cpp
@@ -446,8 +446,7 @@
                     }
                     bundle.setCustomPackage(argv[0]);
                 } else if (strcmp(cp, "-utf16") == 0) {
-                    bundle.setEncodingSpecified(true);
-                    bundle.setUTF8(false);
+                    bundle.setWantUTF16(true);
                 } else if (strcmp(cp, "-rename-manifest-package") == 0) {
                     argc--;
                     argv++;
diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index c0ebb59..87f2420 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -226,7 +226,7 @@
                 if (minSdkIndex >= 0) {
                     const uint16_t* minSdk16 = block.getAttributeStringValue(minSdkIndex, &len);
                     const char* minSdk8 = strdup(String8(minSdk16).string());
-                    bundle->setMinSdkVersion(minSdk8);
+                    bundle->setManifestMinSdkVersion(minSdk8);
                 }
             }
         }
@@ -768,7 +768,13 @@
 
     // Standard flags for compiled XML and optional UTF-8 encoding
     int xmlFlags = XML_COMPILE_STANDARD_RESOURCE;
-    if (bundle->getUTF8()) {
+
+    /* Only enable UTF-8 if the caller of aapt didn't specifically
+     * request UTF-16 encoding and the parameters of this package
+     * allow UTF-8 to be used.
+     */
+    if (!bundle->getWantUTF16()
+            && bundle->isUTF8Available()) {
         xmlFlags |= XML_COMPILE_UTF8;
     }
 
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index ab5e937..66db450 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -2527,9 +2527,11 @@
     const size_t N = mOrderedPackages.size();
     size_t pi;
 
+    bool useUTF8 = !bundle->getWantUTF16() && bundle->isUTF8Available();
+
     // Iterate through all data, collecting all values (strings,
     // references, etc).
-    StringPool valueStrings = StringPool(false, bundle->getUTF8());
+    StringPool valueStrings = StringPool(false, useUTF8);
     for (pi=0; pi<N; pi++) {
         sp<Package> p = mOrderedPackages.itemAt(pi);
         if (p->getTypes().size() == 0) {
@@ -2537,8 +2539,8 @@
             continue;
         }
 
-        StringPool typeStrings = StringPool(false, bundle->getUTF8());
-        StringPool keyStrings = StringPool(false, bundle->getUTF8());
+        StringPool typeStrings = StringPool(false, useUTF8);
+        StringPool keyStrings = StringPool(false, useUTF8);
 
         const size_t N = p->getOrderedTypes().size();
         for (size_t ti=0; ti<N; ti++) {