Add death recipient to TelephonyRegistry.

Add death recipient to TelephonyRegistry so that all binders that
connect to TelephonyRegistry will be cleaned when they are died.

Test: manual
Bug: 73107019
Change-Id: Ib44f72b769272cef9f36f7b49097091a93bcc70e
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 6747be3..5e5eacb 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -64,6 +64,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.NoSuchElementException;
 
 /**
  * Since phone process can be restarted, this class provides a centralized place
@@ -90,6 +91,8 @@
 
         IBinder binder;
 
+        TelephonyRegistryDeathRecipient deathRecipient;
+
         IPhoneStateListener callback;
         IOnSubscriptionsChangedListener onSubscriptionsChangedListenerCallback;
 
@@ -251,6 +254,21 @@
         }
     };
 
+    private class TelephonyRegistryDeathRecipient implements IBinder.DeathRecipient {
+
+        private final IBinder binder;
+
+        TelephonyRegistryDeathRecipient(IBinder binder) {
+            this.binder = binder;
+        }
+
+        @Override
+        public void binderDied() {
+            if (DBG) log("binderDied " + binder);
+            remove(binder);
+        }
+    }
+
     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
@@ -378,23 +396,14 @@
             }
         }
 
-        Record r;
 
         synchronized (mRecords) {
             // register
-            find_and_add: {
-                IBinder b = callback.asBinder();
-                final int N = mRecords.size();
-                for (int i = 0; i < N; i++) {
-                    r = mRecords.get(i);
-                    if (b == r.binder) {
-                        break find_and_add;
-                    }
-                }
-                r = new Record();
-                r.binder = b;
-                mRecords.add(r);
-                if (DBG) log("listen oscl: add new record");
+            IBinder b = callback.asBinder();
+            Record r = add(b);
+
+            if (r == null) {
+                return;
             }
 
             r.onSubscriptionsChangedListenerCallback = callback;
@@ -496,20 +505,11 @@
 
             synchronized (mRecords) {
                 // register
-                Record r;
-                find_and_add: {
-                    IBinder b = callback.asBinder();
-                    final int N = mRecords.size();
-                    for (int i = 0; i < N; i++) {
-                        r = mRecords.get(i);
-                        if (b == r.binder) {
-                            break find_and_add;
-                        }
-                    }
-                    r = new Record();
-                    r.binder = b;
-                    mRecords.add(r);
-                    if (DBG) log("listen: add new record");
+                IBinder b = callback.asBinder();
+                Record r = add(b);
+
+                if (r == null) {
+                    return;
                 }
 
                 r.callback = callback;
@@ -697,16 +697,57 @@
         return record.canReadPhoneState ? mCallIncomingNumber[phoneId] : "";
     }
 
+    private Record add(IBinder binder) {
+        Record r;
+
+        synchronized (mRecords) {
+            final int N = mRecords.size();
+            for (int i = 0; i < N; i++) {
+                r = mRecords.get(i);
+                if (binder == r.binder) {
+                    // Already existed.
+                    return r;
+                }
+            }
+            r = new Record();
+            r.binder = binder;
+            r.deathRecipient = new TelephonyRegistryDeathRecipient(binder);
+
+            try {
+                binder.linkToDeath(r.deathRecipient, 0);
+            } catch (RemoteException e) {
+                if (VDBG) log("LinkToDeath remote exception sending to r=" + r + " e=" + e);
+                // Binder already died. Return null.
+                return null;
+            }
+
+            mRecords.add(r);
+            if (DBG) log("add new record");
+        }
+
+        return r;
+    }
+
     private void remove(IBinder binder) {
         synchronized (mRecords) {
             final int recordCount = mRecords.size();
             for (int i = 0; i < recordCount; i++) {
-                if (mRecords.get(i).binder == binder) {
+                Record r = mRecords.get(i);
+                if (r.binder == binder) {
                     if (DBG) {
-                        Record r = mRecords.get(i);
-                        log("remove: binder=" + binder + "r.callingPackage" + r.callingPackage
-                                + "r.callback" + r.callback);
+                        log("remove: binder=" + binder + " r.callingPackage " + r.callingPackage
+                                + " r.callback " + r.callback);
                     }
+
+                    if (r.deathRecipient != null) {
+                        try {
+                            binder.unlinkToDeath(r.deathRecipient, 0);
+                        } catch (NoSuchElementException e) {
+                            if (VDBG) log("UnlinkToDeath NoSuchElementException sending to r="
+                                    + r + " e=" + e);
+                        }
+                    }
+
                     mRecords.remove(i);
                     return;
                 }