diff options
author | Ryan Lothian <rjlothian@google.com> | 2017-12-04 11:56:58 -0500 |
---|---|---|
committer | android-build-team Robot <android-build-team-robot@google.com> | 2018-02-09 21:28:03 +0000 |
commit | 0748edce4a8741611d0d856534ec8a5abeb920e5 (patch) | |
tree | b4cbd3d1f5bef0f1b30a644d5e33278d12116569 | |
parent | fef1a3e7ca5ab18ede42c5729661459fcd691e09 (diff) | |
download | base-0748edce4a8741611d0d856534ec8a5abeb920e5.tar.gz |
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: manual, crashed listener on proc start, verified not unbound forever
Change-Id: Id2082744208e21a709d9453365f282449a2e9407
(cherry picked from commit 4a86a51b672617b02994fc812e4f96342daf424e)
(cherry picked from commit 1936097afc3188ed5f2bb4e7211bb404364eeb38)
-rw-r--r-- | services/core/java/com/android/server/notification/ManagedServices.java | 29 |
1 files changed, 29 insertions, 0 deletions
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<ManagedServiceInfo> mServices = new ArrayList<>(); // things that will be put into mServices as soon as they're ready private final ArrayList<String> mServicesBinding = new ArrayList<>(); + private final ArraySet<String> mServicesRebinding = new ArraySet<>(); + // lists the component names of all enabled (and therefore potentially connected) // app services for current profiles. private ArraySet<ComponentName> 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, |