From 4b766b38f06935fdfb5c69bc9fd9b3befef0aefd Mon Sep 17 00:00:00 2001 From: Ryan Lothian Date: Mon, 4 Dec 2017 11:56:58 -0500 Subject: [PATCH] Handle onBindingDied in notification manager On Android, if the process containing the service being bound to crashes before the bind succeeds, the app doing the binding won't get a success or failure callback. When that happens in this code, this leaves notif. manager thinking that a binding is in progress, so it never attempts to rebind until the device is rebooted. Bug: 69064494 Test: original CL was manually tested -- crashed listener on proc start, verified not unbound forever Change-Id: Id2082744208e21a709d9453365f282449a2e9407 (cherry picked from commit 4a86a51b672617b02994fc812e4f96342daf424e) --- .../server/notification/ManagedServices.java | 29 ++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java index b7b91a76ebf3..625764cea550 100644 --- a/services/core/java/com/android/server/notification/ManagedServices.java +++ b/services/core/java/com/android/server/notification/ManagedServices.java @@ -39,8 +39,10 @@ import android.content.pm.ServiceInfo; import android.content.pm.UserInfo; import android.os.Binder; import android.os.Build; +import android.os.Handler; import android.os.IBinder; import android.os.IInterface; +import android.os.Looper; import android.os.RemoteException; import android.os.UserHandle; import android.os.UserManager; @@ -82,6 +84,7 @@ abstract public class ManagedServices { protected final String TAG = getClass().getSimpleName(); protected final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); + private static final int ON_BINDING_DIED_REBIND_DELAY_MS = 10000; protected static final String ENABLED_SERVICES_SEPARATOR = ":"; /** @@ -101,12 +104,15 @@ abstract public class ManagedServices { private final IPackageManager mPm; private final UserManager mUm; private final Config mConfig; + private final Handler mHandler = new Handler(Looper.getMainLooper()); // contains connections to all connected services, including app services // and system services private final ArrayList mServices = new ArrayList<>(); // things that will be put into mServices as soon as they're ready private final ArrayList mServicesBinding = new ArrayList<>(); + private final ArraySet mServicesRebinding = new ArraySet<>(); + // lists the component names of all enabled (and therefore potentially connected) // app services for current profiles. private ArraySet mEnabledServicesForCurrentProfiles @@ -823,6 +829,7 @@ abstract public class ManagedServices { final String servicesBindingTag = name.toString() + "/" + userid; if (mServicesBinding.contains(servicesBindingTag)) { + Slog.v(TAG, "Not registering " + name + " as bind is already in progress"); // stop registering this thing already! we're working on it return; } @@ -871,6 +878,7 @@ abstract public class ManagedServices { boolean added = false; ManagedServiceInfo info = null; synchronized (mMutex) { + mServicesRebinding.remove(servicesBindingTag); mServicesBinding.remove(servicesBindingTag); try { mService = asInterface(binder); @@ -892,6 +900,27 @@ abstract public class ManagedServices { mServicesBinding.remove(servicesBindingTag); Slog.v(TAG, getCaption() + " connection lost: " + name); } + + @Override + public void onBindingDied(ComponentName name) { + Slog.w(TAG, getCaption() + " binding died: " + name); + synchronized (mMutex) { + mServicesBinding.remove(servicesBindingTag); + mContext.unbindService(this); + if (!mServicesRebinding.contains(servicesBindingTag)) { + mServicesRebinding.add(servicesBindingTag); + mHandler.postDelayed(new Runnable() { + @Override + public void run() { + registerService(name, userid); + } + }, ON_BINDING_DIED_REBIND_DELAY_MS); + } else { + Slog.v(TAG, getCaption() + " not rebinding as " + + "a previous rebind attempt was made: " + name); + } + } + } }; if (!mContext.bindServiceAsUser(intent, serviceConnection, -- 2.11.0