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

Commit ce522835 authored by Daichi Hirono's avatar Daichi Hirono
Browse files

Stop holding mProxyLock while downloading PAC script data.

Holding PacManager#mProxyLock for long time eventually causes ANR when
launching new applications.

1. ActivityThread#handleBindApplication blocks until

   ActivityThread#handleBindApplication
   -> ConnectivityService#getProxyForNetwork()
   -> ConnectivityService#getDefaultProxy()

  obtains the lock of ConnectivityService#mProxyLock

2. ConnectivityService#mProxyLock can be held by
   ConnectivityService#setGlobalProxy() running on another thread until

   ConnectivityService#setGlobalProxy()
   -> ConnectivityService#sendProxyBroadcast()
   -> PacManager#setCurrentProxyScriptUrl()

  obtains the lock of PacManager#mProxyLock

3. Before the CL, PacManager#mProxyLock could be held by
   mPacDownloader#run() on mNetThread until downloading a PAC script
   completed.

The CL fixes the step 3 so that mPacDownloader#run does not keep the
lock of PacManager#mProxyLock. It eventually fixes long blocking at
ActivityThread#handleBindApplication and ANR when launching an
application.

Bug: 36317236
Test: Build succeeded
Merged-In: I864e41e1142178681f8f1b4fb7750d37e3ab2076
Change-Id: I864e41e1142178681f8f1b4fb7750d37e3ab2076
parent 58ba53bd
Loading
Loading
Loading
Loading
+19 −15
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
 */
package com.android.server.connectivity;

import android.annotation.WorkerThread;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
@@ -73,7 +74,7 @@ public class PacManager {
    public static final String KEY_PROXY = "keyProxy";
    private String mCurrentPac;
    @GuardedBy("mProxyLock")
    private Uri mPacUrl = Uri.EMPTY;
    private volatile Uri mPacUrl = Uri.EMPTY;

    private AlarmManager mAlarmManager;
    @GuardedBy("mProxyLock")
@@ -86,30 +87,35 @@ public class PacManager {
    private int mCurrentDelay;
    private int mLastPort;

    private boolean mHasSentBroadcast;
    private boolean mHasDownloaded;
    private volatile boolean mHasSentBroadcast;
    private volatile boolean mHasDownloaded;

    private Handler mConnectivityHandler;
    private int mProxyMessage;

    /**
     * Used for locking when setting mProxyService and all references to mPacUrl or mCurrentPac.
     * Used for locking when setting mProxyService and all references to mCurrentPac.
     */
    private final Object mProxyLock = new Object();

    /**
     * Runnable to download PAC script.
     * The behavior relies on the assamption it always run on mNetThread to guarantee that the
     * latest data fetched from mPacUrl is stored in mProxyService.
     */
    private Runnable mPacDownloader = new Runnable() {
        @Override
        @WorkerThread
        public void run() {
            String file;
            synchronized (mProxyLock) {
                if (Uri.EMPTY.equals(mPacUrl)) return;
            final Uri pacUrl = mPacUrl;
            if (Uri.EMPTY.equals(pacUrl)) return;
            try {
                    file = get(mPacUrl);
                file = get(pacUrl);
            } catch (IOException ioe) {
                file = null;
                Log.w(TAG, "Failed to load PAC file: " + ioe);
            }
            }
            if (file != null) {
                synchronized (mProxyLock) {
                    if (!file.equals(mCurrentPac)) {
@@ -171,9 +177,7 @@ public class PacManager {
                // Allow to send broadcast, nothing to do.
                return false;
            }
            synchronized (mProxyLock) {
            mPacUrl = proxy.getPacFileUrl();
            }
            mCurrentDelay = DELAY_1;
            mHasSentBroadcast = false;
            mHasDownloaded = false;