bugfix for: OOM error while doing voice search repeatedly

fix for: http://b/issue?id=2599931

Change-Id: Ic27d9eb8b29afa99787e469d9248c20f7d2988de
diff --git a/core/java/android/speech/RecognitionService.java b/core/java/android/speech/RecognitionService.java
index 5a0959a..1c1fa95 100644
--- a/core/java/android/speech/RecognitionService.java
+++ b/core/java/android/speech/RecognitionService.java
@@ -53,6 +53,9 @@
     /** Debugging flag */
     private static final boolean DBG = false;
 
+    /** Binder of the recognition service */
+    private RecognitionServiceBinder mBinder = new RecognitionServiceBinder(this);
+
     /**
      * The current callback of an application that invoked the
      * {@link RecognitionService#onStartListening(Intent, Callback)} method
@@ -136,31 +139,6 @@
         }
     }
 
-    /** Binder of the recognition service */
-    private final IRecognitionService.Stub mBinder = new IRecognitionService.Stub() {
-        public void startListening(Intent recognizerIntent, IRecognitionListener listener) {
-            if (DBG) Log.d(TAG, "startListening called by:" + listener.asBinder());
-            if (checkPermissions(listener)) {
-                mHandler.sendMessage(Message.obtain(mHandler, MSG_START_LISTENING,
-                        new StartListeningArgs(recognizerIntent, listener)));
-            }
-        }
-
-        public void stopListening(IRecognitionListener listener) {
-            if (DBG) Log.d(TAG, "stopListening called by:" + listener.asBinder());
-            if (checkPermissions(listener)) {
-                mHandler.sendMessage(Message.obtain(mHandler, MSG_STOP_LISTENING, listener));
-            }
-        }
-
-        public void cancel(IRecognitionListener listener) {
-            if (DBG) Log.d(TAG, "cancel called by:" + listener.asBinder());
-            if (checkPermissions(listener)) {
-                mHandler.sendMessage(Message.obtain(mHandler, MSG_CANCEL, listener));
-            }
-        }
-    };
-
     /**
      * Checks whether the caller has sufficient permissions
      * 
@@ -210,6 +188,14 @@
         return mBinder;
     }
 
+    @Override
+    public void onDestroy() {
+        if (DBG) Log.d(TAG, "onDestroy");
+        mCurrentCallback = null;
+        mBinder.clearReference();
+        super.onDestroy();
+    }
+
     /**
      * This class receives callbacks from the speech recognition service and forwards them to the
      * user. An instance of this class is passed to the
@@ -306,4 +292,42 @@
             mListener.onRmsChanged(rmsdB);
         }
     }
+
+    /** Binder of the recognition service */
+    private static class RecognitionServiceBinder extends IRecognitionService.Stub {
+        private RecognitionService mInternalService;
+
+        public RecognitionServiceBinder(RecognitionService service) {
+            mInternalService = service;
+        }
+
+        public void startListening(Intent recognizerIntent, IRecognitionListener listener) {
+            if (DBG) Log.d(TAG, "startListening called by:" + listener.asBinder());
+            if (mInternalService != null && mInternalService.checkPermissions(listener)) {
+                mInternalService.mHandler.sendMessage(Message.obtain(mInternalService.mHandler,
+                        MSG_START_LISTENING, mInternalService.new StartListeningArgs(
+                                recognizerIntent, listener)));
+            }
+        }
+
+        public void stopListening(IRecognitionListener listener) {
+            if (DBG) Log.d(TAG, "stopListening called by:" + listener.asBinder());
+            if (mInternalService != null && mInternalService.checkPermissions(listener)) {
+                mInternalService.mHandler.sendMessage(Message.obtain(mInternalService.mHandler,
+                        MSG_STOP_LISTENING, listener));
+            }
+        }
+
+        public void cancel(IRecognitionListener listener) {
+            if (DBG) Log.d(TAG, "cancel called by:" + listener.asBinder());
+            if (mInternalService != null && mInternalService.checkPermissions(listener)) {
+                mInternalService.mHandler.sendMessage(Message.obtain(mInternalService.mHandler,
+                        MSG_CANCEL, listener));
+            }
+        }
+
+        public void clearReference() {
+            mInternalService = null;
+        }
+    }
 }
diff --git a/core/java/android/speech/SpeechRecognizer.java b/core/java/android/speech/SpeechRecognizer.java
index 7f9a12b..8fa0d59 100644
--- a/core/java/android/speech/SpeechRecognizer.java
+++ b/core/java/android/speech/SpeechRecognizer.java
@@ -382,6 +382,7 @@
         mPendingTasks.clear();
         mService = null;
         mConnection = null;
+        mListener.mInternalListener = null;
     }
 
     /**