Merge "Purge CallLog."
diff --git a/core/java/android/server/search/SearchManagerService.java b/core/java/android/server/search/SearchManagerService.java
index 2eebe77..caa3144 100644
--- a/core/java/android/server/search/SearchManagerService.java
+++ b/core/java/android/server/search/SearchManagerService.java
@@ -16,20 +16,14 @@
 
 package android.server.search;
 
-import android.app.ActivityManagerNative;
-import android.app.IActivityWatcher;
+import com.android.internal.content.PackageMonitor;
+
 import android.app.ISearchManager;
-import android.app.ISearchManagerCallback;
 import android.app.SearchManager;
 import android.app.SearchableInfo;
-import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.RemoteException;
 import android.util.Log;
 
 import java.util.List;
@@ -42,13 +36,11 @@
 
     // general debugging support
     private static final String TAG = "SearchManagerService";
-    private static final boolean DBG = false;
 
     // Context that the service is running in.
     private final Context mContext;
 
-    // This field is initialized in ensureSearchablesCreated(), and then never modified.
-    // Only accessed by ensureSearchablesCreated() and getSearchables()
+    // This field is initialized lazily in getSearchables(), and then never modified.
     private Searchables mSearchables;
 
     /**
@@ -61,58 +53,28 @@
         mContext = context;
     }
 
-    private synchronized void ensureSearchablesCreated() {
-        if (mSearchables != null) return;  // already created
-
-        mSearchables = new Searchables(mContext);
-        mSearchables.buildSearchableList();
-
-        IntentFilter packageFilter = new IntentFilter();
-        packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
-        packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
-        packageFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
-        packageFilter.addDataScheme("package");
-        mContext.registerReceiver(mPackageChangedReceiver, packageFilter);
-        // Register for events related to sdcard installation.
-        IntentFilter sdFilter = new IntentFilter();
-        sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
-        sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
-        mContext.registerReceiver(mPackageChangedReceiver, sdFilter);
-    }
-
     private synchronized Searchables getSearchables() {
-        ensureSearchablesCreated();
+        if (mSearchables == null) {
+            mSearchables = new Searchables(mContext);
+            mSearchables.buildSearchableList();
+            new MyPackageMonitor().register(mContext, true);
+        }
         return mSearchables;
     }
 
     /**
      * Refreshes the "searchables" list when packages are added/removed.
      */
-    private BroadcastReceiver mPackageChangedReceiver = new BroadcastReceiver() {
+    class MyPackageMonitor extends PackageMonitor {
         @Override
-        public void onReceive(Context context, Intent intent) {
-            String action = intent.getAction();
-
-            if (Intent.ACTION_PACKAGE_ADDED.equals(action) ||
-                    Intent.ACTION_PACKAGE_REMOVED.equals(action) ||
-                    Intent.ACTION_PACKAGE_CHANGED.equals(action) ||
-                    Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action) ||
-                    Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
-                if (DBG) Log.d(TAG, "Got " + action);
-                // Update list of searchable activities
-                getSearchables().buildSearchableList();
-                broadcastSearchablesChanged();
-            }
+        public void onSomePackagesChanged() {
+            // Update list of searchable activities
+            getSearchables().buildSearchableList();
+            // Inform all listeners that the list of searchables has been updated.
+            Intent intent = new Intent(SearchManager.INTENT_ACTION_SEARCHABLES_CHANGED);
+            intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
+            mContext.sendBroadcast(intent);
         }
-    };
-
-    /**
-     * Informs all listeners that the list of searchables has been updated.
-     */
-    void broadcastSearchablesChanged() {
-        Intent intent = new Intent(SearchManager.INTENT_ACTION_SEARCHABLES_CHANGED);
-        intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
-        mContext.sendBroadcast(intent);
     }
 
     //
diff --git a/libs/audioflinger/AudioPolicyManagerBase.cpp b/libs/audioflinger/AudioPolicyManagerBase.cpp
index 096aa73..42b6508 100644
--- a/libs/audioflinger/AudioPolicyManagerBase.cpp
+++ b/libs/audioflinger/AudioPolicyManagerBase.cpp
@@ -295,13 +295,31 @@
     if (oldState == AudioSystem::MODE_IN_CALL && newDevice == 0) {
         newDevice = hwOutputDesc->device();
     }
+
+    // when changing from ring tone to in call mode, mute the ringing tone
+    // immediately and delay the route change to avoid sending the ring tone
+    // tail into the earpiece or headset.
+    int delayMs = 0;
+    if (state == AudioSystem::MODE_IN_CALL && oldState == AudioSystem::MODE_RINGTONE) {
+        // delay the device change command by twice the output latency to have some margin
+        // and be sure that audio buffers not yet affected by the mute are out when
+        // we actually apply the route change
+        delayMs = hwOutputDesc->mLatency*2;
+        setStreamMute(AudioSystem::RING, true, mHardwareOutput);
+    }
+
     // change routing is necessary
-    setOutputDevice(mHardwareOutput, newDevice, force);
+    setOutputDevice(mHardwareOutput, newDevice, force, delayMs);
 
     // if entering in call state, handle special case of active streams
     // pertaining to sonification strategy see handleIncallSonification()
     if (state == AudioSystem::MODE_IN_CALL) {
         LOGV("setPhoneState() in call state management: new state is %d", state);
+        // unmute the ringing tone after a sufficient delay if it was muted before
+        // setting output device above
+        if (oldState == AudioSystem::MODE_RINGTONE) {
+            setStreamMute(AudioSystem::RING, false, mHardwareOutput, MUTE_TIME_MS);
+        }
         for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) {
             handleIncallSonification(stream, true, true);
         }
@@ -1207,10 +1225,10 @@
         return INVALID_OPERATION;
     }
 
-    // mute media during 2 seconds to avoid outputing sound on hardware output while music stream
+    // mute media strategy to avoid outputting sound on hardware output while music stream
     // is switched from A2DP output and before music is paused by music application
     setStrategyMute(STRATEGY_MEDIA, true, mHardwareOutput);
-    setStrategyMute(STRATEGY_MEDIA, false, mHardwareOutput, 2000);
+    setStrategyMute(STRATEGY_MEDIA, false, mHardwareOutput, MUTE_TIME_MS);
 
     if (!a2dpUsedForSonification()) {
         // unmute music on A2DP output if a notification or ringtone is playing