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

Commit b17d1a36 authored by Jeremy Joslin's avatar Jeremy Joslin Committed by android-build-merger
Browse files

Merge "Fix issue #28930592: Scoring service binding is not reestablished." into nyc-dev

am: 49b515a2

* commit '49b515a2':
  Fix issue #28930592: Scoring service binding is not reestablished.

Change-Id: I3fdb0cb78e2991810ee7e62e901638be71272895
parents a23ed40a 49b515a2
Loading
Loading
Loading
Loading
+92 −52
Original line number Original line Diff line number Diff line
@@ -17,12 +17,10 @@
package com.android.server;
package com.android.server;


import android.Manifest.permission;
import android.Manifest.permission;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Context;
import android.content.Intent;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager;
import android.net.INetworkScoreCache;
import android.net.INetworkScoreCache;
@@ -33,7 +31,6 @@ import android.net.NetworkScorerAppManager.NetworkScorerAppData;
import android.net.ScoredNetwork;
import android.net.ScoredNetwork;
import android.os.Binder;
import android.os.Binder;
import android.os.IBinder;
import android.os.IBinder;
import android.os.PatternMatcher;
import android.os.RemoteException;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserHandle;
import android.provider.Settings;
import android.provider.Settings;
@@ -42,6 +39,7 @@ import android.util.Log;


import com.android.internal.R;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.content.PackageMonitor;


import java.io.FileDescriptor;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.io.PrintWriter;
@@ -62,39 +60,75 @@ public class NetworkScoreService extends INetworkScoreService.Stub {


    private final Context mContext;
    private final Context mContext;
    private final Map<Integer, INetworkScoreCache> mScoreCaches;
    private final Map<Integer, INetworkScoreCache> mScoreCaches;
    /** Lock used to update mReceiver when scorer package changes occur. */
    /** Lock used to update mPackageMonitor when scorer package changes occur. */
    private final Object mReceiverLock = new Object[0];
    private final Object mPackageMonitorLock = new Object[0];


    /** Clears scores when the active scorer package is no longer valid. */
    @GuardedBy("mPackageMonitorLock")
    @GuardedBy("mReceiverLock")
    private NetworkScorerPackageMonitor mPackageMonitor;
    private ScorerChangedReceiver mReceiver;
    private ScoringServiceConnection mServiceConnection;
    private ScoringServiceConnection mServiceConnection;


    private class ScorerChangedReceiver extends BroadcastReceiver {
    /**
     * Clears scores when the active scorer package is no longer valid and
     * manages the service connection.
     */
    private class NetworkScorerPackageMonitor extends PackageMonitor {
        final String mRegisteredPackage;
        final String mRegisteredPackage;


        ScorerChangedReceiver(String packageName) {
        private NetworkScorerPackageMonitor(String mRegisteredPackage) {
            mRegisteredPackage = packageName;
            this.mRegisteredPackage = mRegisteredPackage;
        }

        @Override
        public void onPackageAdded(String packageName, int uid) {
            evaluateBinding(packageName, true /* forceUnbind */);
        }

        @Override
        public void onPackageRemoved(String packageName, int uid) {
            evaluateBinding(packageName, true /* forceUnbind */);
        }

        @Override
        public void onPackageModified(String packageName) {
            evaluateBinding(packageName, false /* forceUnbind */);
        }

        @Override
        public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) {
            if (doit) { // "doit" means the force stop happened instead of just being queried for.
                for (String packageName : packages) {
                    evaluateBinding(packageName, true /* forceUnbind */);
                }
            }
            return super.onHandleForceStop(intent, packages, uid, doit);
        }
        }


        @Override
        @Override
        public void onReceive(Context context, Intent intent) {
        public void onPackageUpdateFinished(String packageName, int uid) {
            String action = intent.getAction();
            evaluateBinding(packageName, true /* forceUnbind */);
            if (Intent.ACTION_PACKAGE_CHANGED.equals(action)
        }
                    || Intent.ACTION_PACKAGE_REPLACED.equals(action)

                    || Intent.ACTION_PACKAGE_FULLY_REMOVED.equals(action)) {
        private void evaluateBinding(String scorerPackageName, boolean forceUnbind) {
                NetworkScorerAppData activeScorer =
            if (mRegisteredPackage.equals(scorerPackageName)) {
                if (DBG) {
                    Log.d(TAG, "Evaluating binding for: " + scorerPackageName
                            + ", forceUnbind=" + forceUnbind);
                }
                final NetworkScorerAppData activeScorer =
                        NetworkScorerAppManager.getActiveScorer(mContext);
                        NetworkScorerAppManager.getActiveScorer(mContext);
                if (activeScorer == null) {
                if (activeScorer == null) {
                    // Package change has invalidated a scorer.
                    // Package change has invalidated a scorer, this will also unbind any service
                    // connection.
                    Log.i(TAG, "Package " + mRegisteredPackage +
                    Log.i(TAG, "Package " + mRegisteredPackage +
                            " is no longer valid, disabling scoring.");
                            " is no longer valid, disabling scoring.");
                    setScorerInternal(null);
                    setScorerInternal(null);
                } else if (activeScorer.mScoringServiceClassName == null) {
                } else if (activeScorer.mScoringServiceClassName == null) {
                    // The scoring service is not available, make sure it's unbound.
                    // The scoring service is not available, make sure it's unbound.
                    unbindFromScoringServiceIfNeeded();
                    unbindFromScoringServiceIfNeeded();
                } else {
                } else { // The scoring service changed in some way.
                    // The scoring service may have changed or been added.
                    if (forceUnbind) {
                        unbindFromScoringServiceIfNeeded();
                    }
                    bindToScoringServiceIfNeeded(activeScorer);
                    bindToScoringServiceIfNeeded(activeScorer);
                }
                }
            }
            }
@@ -121,7 +155,7 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
            Settings.Global.putInt(cr, Settings.Global.NETWORK_SCORING_PROVISIONED, 1);
            Settings.Global.putInt(cr, Settings.Global.NETWORK_SCORING_PROVISIONED, 1);
        }
        }


        registerPackageReceiverIfNeeded();
        registerPackageMonitorIfNeeded();
    }
    }


    /** Called when the system is ready for us to start third-party code. */
    /** Called when the system is ready for us to start third-party code. */
@@ -130,33 +164,29 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
        bindToScoringServiceIfNeeded();
        bindToScoringServiceIfNeeded();
    }
    }


    private void registerPackageReceiverIfNeeded() {
    private void registerPackageMonitorIfNeeded() {
        if (DBG) Log.d(TAG, "registerPackageReceiverIfNeeded");
        if (DBG) Log.d(TAG, "registerPackageMonitorIfNeeded");
        NetworkScorerAppData scorer = NetworkScorerAppManager.getActiveScorer(mContext);
        NetworkScorerAppData scorer = NetworkScorerAppManager.getActiveScorer(mContext);
        synchronized (mReceiverLock) {
        synchronized (mPackageMonitorLock) {
            // Unregister the receiver if the current scorer has changed since last registration.
            // Unregister the current monitor if needed.
            if (mReceiver != null) {
            if (mPackageMonitor != null) {
                if (Log.isLoggable(TAG, Log.VERBOSE)) {
                if (DBG) {
                    Log.v(TAG, "Unregistering receiver for " + mReceiver.mRegisteredPackage);
                    Log.d(TAG, "Unregistering package monitor for "
                            + mPackageMonitor.mRegisteredPackage);
                }
                }
                mContext.unregisterReceiver(mReceiver);
                mPackageMonitor.unregister();
                mReceiver = null;
                mPackageMonitor = null;
            }
            }


            // Register receiver if a scorer is active.
            // Create and register the monitor if a scorer is active.
            if (scorer != null) {
            if (scorer != null) {
                IntentFilter filter = new IntentFilter();
                mPackageMonitor = new NetworkScorerPackageMonitor(scorer.mPackageName);
                filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
                filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
                filter.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED);
                filter.addDataScheme("package");
                filter.addDataSchemeSpecificPart(scorer.mPackageName,
                        PatternMatcher.PATTERN_LITERAL);
                mReceiver = new ScorerChangedReceiver(scorer.mPackageName);
                // TODO: Need to update when we support per-user scorers. http://b/23422763
                // TODO: Need to update when we support per-user scorers. http://b/23422763
                mContext.registerReceiverAsUser(mReceiver, UserHandle.SYSTEM, filter, null, null);
                mPackageMonitor.register(mContext, null /* thread */, UserHandle.SYSTEM,
                if (Log.isLoggable(TAG, Log.VERBOSE)) {
                        false /* externalStorage */);
                    Log.v(TAG, "Registered receiver for " + scorer.mPackageName);
                if (DBG) {
                    Log.d(TAG, "Registered package monitor for "
                            + mPackageMonitor.mRegisteredPackage);
                }
                }
            }
            }
        }
        }
@@ -299,7 +329,7 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
            // will be made to bind to the new scorer.
            // will be made to bind to the new scorer.
            bindToScoringServiceIfNeeded();
            bindToScoringServiceIfNeeded();
            if (result) { // new scorer successfully set
            if (result) { // new scorer successfully set
                registerPackageReceiverIfNeeded();
                registerPackageMonitorIfNeeded();


                Intent intent = new Intent(NetworkScoreManager.ACTION_SCORER_CHANGED);
                Intent intent = new Intent(NetworkScoreManager.ACTION_SCORER_CHANGED);
                if (prevScorer != null) { // Directly notify the old scorer.
                if (prevScorer != null) { // Directly notify the old scorer.
@@ -391,13 +421,14 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
    private static class ScoringServiceConnection implements ServiceConnection {
    private static class ScoringServiceConnection implements ServiceConnection {
        private final ComponentName mComponentName;
        private final ComponentName mComponentName;
        private boolean mBound = false;
        private boolean mBound = false;
        private boolean mConnected = false;


        ScoringServiceConnection(ComponentName componentName) {
        ScoringServiceConnection(ComponentName componentName) {
            mComponentName = componentName;
            mComponentName = componentName;
        }
        }


        void connect(Context context) {
        void connect(Context context) {
            disconnect(context);
            if (!mBound) {
                Intent service = new Intent();
                Intent service = new Intent();
                service.setComponent(mComponentName);
                service.setComponent(mComponentName);
                mBound = context.bindServiceAsUser(service, this,
                mBound = context.bindServiceAsUser(service, this,
@@ -405,6 +436,9 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
                        UserHandle.SYSTEM);
                        UserHandle.SYSTEM);
                if (!mBound) {
                if (!mBound) {
                    Log.w(TAG, "Bind call failed for " + service);
                    Log.w(TAG, "Bind call failed for " + service);
                } else {
                    if (DBG) Log.d(TAG, "ScoringServiceConnection bound.");
                }
            }
            }
        }
        }


@@ -413,6 +447,7 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
                if (mBound) {
                if (mBound) {
                    mBound = false;
                    mBound = false;
                    context.unbindService(this);
                    context.unbindService(this);
                    if (DBG) Log.d(TAG, "ScoringServiceConnection unbound.");
                }
                }
            } catch (RuntimeException e) {
            } catch (RuntimeException e) {
                Log.e(TAG, "Unbind failed.", e);
                Log.e(TAG, "Unbind failed.", e);
@@ -422,15 +457,20 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
        @Override
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
        public void onServiceConnected(ComponentName name, IBinder service) {
            if (DBG) Log.d(TAG, "ScoringServiceConnection: " + name.flattenToString());
            if (DBG) Log.d(TAG, "ScoringServiceConnection: " + name.flattenToString());
            mConnected = true;
        }
        }


        @Override
        @Override
        public void onServiceDisconnected(ComponentName name) {
        public void onServiceDisconnected(ComponentName name) {
            if (DBG) Log.d(TAG, "ScoringServiceConnection, disconnected: " + name.flattenToString());
            if (DBG) {
                Log.d(TAG, "ScoringServiceConnection, disconnected: " + name.flattenToString());
            }
            mConnected = false;
        }
        }


        public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
        public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
            writer.println("ScoringServiceConnection: " + mComponentName + ", bound: " + mBound);
            writer.println("ScoringServiceConnection: " + mComponentName + ", bound: " + mBound
                    + ", connected: " + mConnected);
        }
        }
    }
    }
}
}