Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1a78d8c2 authored by Christopher Tate's avatar Christopher Tate
Browse files

Rebind backup transports only when clearly needed

Significantly narrow the circumstances under which transports
will be re-bound.  In particular, we now do not unbind + rebind
whenever any component in a bound transport's host package changes;
rather, we do so only when the transport component itself has
changed state, or when there is a state change that might cause
a new transport to become available.

Bug 19775237

Change-Id: Ib386875df19ffe9f2d3eb9f9788187338360644a
parent 0c4729a1
Loading
Loading
Loading
Loading
+51 −11
Original line number Diff line number Diff line
@@ -1725,28 +1725,68 @@ public class BackupManagerService {
                // At package-changed we only care about looking at new transport states
                if (changed) {
                    try {
                        String[] components =
                                intent.getStringArrayExtra(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST);

                        if (MORE_DEBUG) {
                            Slog.i(TAG, "Package " + pkgName + " changed; rechecking");
                            for (int i = 0; i < components.length; i++) {
                                Slog.i(TAG, "   * " + components[i]);
                            }
                        }
                        // unbind existing possibly-stale connections to that package's transports

                        // In general we need to try to bind any time we see a component enable
                        // state change, because that change may have made a transport available.
                        // However, because we currently only support a single transport component
                        // per package, we can skip the bind attempt if the change (a) affects a
                        // package known to host a transport, but (b) does not affect the known
                        // transport component itself.
                        //
                        // In addition, if the change *is* to a known transport component, we need
                        // to unbind it before retrying the binding.
                        boolean tryBind = true;
                        synchronized (mTransports) {
                            TransportConnection conn = mTransportConnections.get(pkgName);
                            if (conn != null) {
                                // We have a bound transport in this package; do we need to rebind it?
                                final ServiceInfo svc = conn.mTransport;
                                ComponentName svcName =
                                        new ComponentName(svc.packageName, svc.name);
                                String flatName = svcName.flattenToShortString();
                                Slog.i(TAG, "Unbinding " + svcName);

                                if (svc.packageName.equals(pkgName)) {
                                    final String className = svcName.getClassName();
                                    if (MORE_DEBUG) {
                                        Slog.i(TAG, "Checking need to rebind " + className);
                                    }
                                    // See whether it's the transport component within this package
                                    boolean isTransport = false;
                                    for (int i = 0; i < components.length; i++) {
                                        if (className.equals(components[i])) {
                                            // Okay, it's an existing transport component.
                                            final String flatName = svcName.flattenToShortString();
                                            mContext.unbindService(conn);
                                            mTransportConnections.remove(pkgName);
                                            mTransports.remove(mTransportNames.get(flatName));
                                            mTransportNames.remove(flatName);
                                            isTransport = true;
                                            break;
                                        }
                                    }
                        // and then (re)bind as appropriate
                                    if (!isTransport) {
                                        // A non-transport component within a package that is hosting
                                        // a bound transport
                                        tryBind = false;
                                    }
                                }
                            }
                        }
                        // and now (re)bind as appropriate
                        if (tryBind) {
                            if (MORE_DEBUG) {
                                Slog.i(TAG, "Yes, need to recheck binding");
                            }
                            PackageInfo app = mPackageManager.getPackageInfo(pkgName, 0);
                            checkForTransportAndBind(app);
                        }
                    } catch (NameNotFoundException e) {
                        // Nope, can't find it - just ignore
                        if (MORE_DEBUG) {