FileDocCategorySizeDatePackage
PacManager.javaAPI DocAndroid 5.1 API13581Thu Mar 12 22:22:42 GMT 2015com.android.server.connectivity

PacManager

public class PacManager extends Object
hide

Fields Summary
public static final String
PAC_PACKAGE
public static final String
PAC_SERVICE
public static final String
PAC_SERVICE_NAME
public static final String
PROXY_PACKAGE
public static final String
PROXY_SERVICE
private static final String
TAG
private static final String
ACTION_PAC_REFRESH
private static final String
DEFAULT_DELAYS
private static final int
DELAY_1
private static final int
DELAY_4
private static final int
DELAY_LONG
public static final String
KEY_PROXY
Keep these values up-to-date with ProxyService.java
private String
mCurrentPac
private android.net.Uri
mPacUrl
private android.app.AlarmManager
mAlarmManager
private com.android.net.IProxyService
mProxyService
private android.app.PendingIntent
mPacRefreshIntent
private android.content.ServiceConnection
mConnection
private android.content.ServiceConnection
mProxyConnection
private android.content.Context
mContext
private int
mCurrentDelay
private int
mLastPort
private boolean
mHasSentBroadcast
private boolean
mHasDownloaded
private android.os.Handler
mConnectivityHandler
private int
mProxyMessage
private final Object
mProxyLock
Used for locking when setting mProxyService and all references to mPacUrl or mCurrentPac.
private Runnable
mPacDownloader
Constructors Summary
public PacManager(android.content.Context context, android.os.Handler handler, int proxyMessage)

        mContext = context;
        mLastPort = -1;

        mPacRefreshIntent = PendingIntent.getBroadcast(
                context, 0, new Intent(ACTION_PAC_REFRESH), 0);
        context.registerReceiver(new PacRefreshIntentReceiver(),
                new IntentFilter(ACTION_PAC_REFRESH));
        mConnectivityHandler = handler;
        mProxyMessage = proxyMessage;
    
Methods Summary
private voidbind()

        if (mContext == null) {
            Log.e(TAG, "No context for binding");
            return;
        }
        Intent intent = new Intent();
        intent.setClassName(PAC_PACKAGE, PAC_SERVICE);
        if ((mProxyConnection != null) && (mConnection != null)) {
            // Already bound no need to bind again, just download the new file.
            IoThread.getHandler().post(mPacDownloader);
            return;
        }
        mConnection = new ServiceConnection() {
            @Override
            public void onServiceDisconnected(ComponentName component) {
                synchronized (mProxyLock) {
                    mProxyService = null;
                }
            }

            @Override
            public void onServiceConnected(ComponentName component, IBinder binder) {
                synchronized (mProxyLock) {
                    try {
                        Log.d(TAG, "Adding service " + PAC_SERVICE_NAME + " "
                                + binder.getInterfaceDescriptor());
                    } catch (RemoteException e1) {
                        Log.e(TAG, "Remote Exception", e1);
                    }
                    ServiceManager.addService(PAC_SERVICE_NAME, binder);
                    mProxyService = IProxyService.Stub.asInterface(binder);
                    if (mProxyService == null) {
                        Log.e(TAG, "No proxy service");
                    } else {
                        try {
                            mProxyService.startPacSystem();
                        } catch (RemoteException e) {
                            Log.e(TAG, "Unable to reach ProxyService - PAC will not be started", e);
                        }
                        IoThread.getHandler().post(mPacDownloader);
                    }
                }
            }
        };
        mContext.bindService(intent, mConnection,
                Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND | Context.BIND_NOT_VISIBLE);

        intent = new Intent();
        intent.setClassName(PROXY_PACKAGE, PROXY_SERVICE);
        mProxyConnection = new ServiceConnection() {
            @Override
            public void onServiceDisconnected(ComponentName component) {
            }

            @Override
            public void onServiceConnected(ComponentName component, IBinder binder) {
                IProxyCallback callbackService = IProxyCallback.Stub.asInterface(binder);
                if (callbackService != null) {
                    try {
                        callbackService.getProxyPort(new IProxyPortListener.Stub() {
                            @Override
                            public void setProxyPort(int port) throws RemoteException {
                                if (mLastPort != -1) {
                                    // Always need to send if port changed
                                    mHasSentBroadcast = false;
                                }
                                mLastPort = port;
                                if (port != -1) {
                                    Log.d(TAG, "Local proxy is bound on " + port);
                                    sendProxyIfNeeded();
                                } else {
                                    Log.e(TAG, "Received invalid port from Local Proxy,"
                                            + " PAC will not be operational");
                                }
                            }
                        });
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        mContext.bindService(intent, mProxyConnection,
                Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND | Context.BIND_NOT_VISIBLE);
    
private static java.lang.Stringget(android.net.Uri pacUri)
Does a post and reports back the status code.

throws
IOException

        URL url = new URL(pacUri.toString());
        URLConnection urlConnection = url.openConnection(java.net.Proxy.NO_PROXY);
        return new String(Streams.readFully(urlConnection.getInputStream()));
    
private android.app.AlarmManagergetAlarmManager()

        if (mAlarmManager == null) {
            mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
        }
        return mAlarmManager;
    
private longgetDownloadDelay(int delayIndex)

        String[] list = getPacChangeDelay().split(" ");
        if (delayIndex < list.length) {
            return Long.parseLong(list[delayIndex]);
        }
        return 0;
    
private intgetNextDelay(int currentDelay)

       if (++currentDelay > DELAY_4) {
           return DELAY_4;
       }
       return currentDelay;
    
private java.lang.StringgetPacChangeDelay()

        final ContentResolver cr = mContext.getContentResolver();

        /** Check system properties for the default value then use secure settings value, if any. */
        String defaultDelay = SystemProperties.get(
                "conn." + Settings.Global.PAC_CHANGE_DELAY,
                DEFAULT_DELAYS);
        String val = Settings.Global.getString(cr, Settings.Global.PAC_CHANGE_DELAY);
        return (val == null) ? defaultDelay : val;
    
private voidlongSchedule()

        mCurrentDelay = DELAY_1;
        setDownloadIn(DELAY_LONG);
    
private voidreschedule()

        mCurrentDelay = getNextDelay(mCurrentDelay);
        setDownloadIn(mCurrentDelay);
    
private voidsendPacBroadcast(android.net.ProxyInfo proxy)

        mConnectivityHandler.sendMessage(mConnectivityHandler.obtainMessage(mProxyMessage, proxy));
    
private synchronized voidsendProxyIfNeeded()

        if (!mHasDownloaded || (mLastPort == -1)) {
            return;
        }
        if (!mHasSentBroadcast) {
            sendPacBroadcast(new ProxyInfo(mPacUrl, mLastPort));
            mHasSentBroadcast = true;
        }
    
private booleansetCurrentProxyScript(java.lang.String script)

        if (mProxyService == null) {
            Log.e(TAG, "setCurrentProxyScript: no proxy service");
            return false;
        }
        try {
            mProxyService.setPacFile(script);
            mCurrentPac = script;
        } catch (RemoteException e) {
            Log.e(TAG, "Unable to set PAC file", e);
        }
        return true;
    
public synchronized booleansetCurrentProxyScriptUrl(android.net.ProxyInfo proxy)
Updates the PAC Manager with current Proxy information. This is called by the ConnectivityService directly before a broadcast takes place to allow the PacManager to indicate that the broadcast should not be sent and the PacManager will trigger a new broadcast when it is ready.

param
proxy Proxy information that is about to be broadcast.
return
Returns true when the broadcast should not be sent

        if (!Uri.EMPTY.equals(proxy.getPacFileUrl())) {
            if (proxy.getPacFileUrl().equals(mPacUrl) && (proxy.getPort() > 0)) {
                // Allow to send broadcast, nothing to do.
                return false;
            }
            synchronized (mProxyLock) {
                mPacUrl = proxy.getPacFileUrl();
            }
            mCurrentDelay = DELAY_1;
            mHasSentBroadcast = false;
            mHasDownloaded = false;
            getAlarmManager().cancel(mPacRefreshIntent);
            bind();
            return true;
        } else {
            getAlarmManager().cancel(mPacRefreshIntent);
            synchronized (mProxyLock) {
                mPacUrl = Uri.EMPTY;
                mCurrentPac = null;
                if (mProxyService != null) {
                    try {
                        mProxyService.stopPacSystem();
                    } catch (RemoteException e) {
                        Log.w(TAG, "Failed to stop PAC service", e);
                    } finally {
                        unbind();
                    }
                }
            }
            return false;
        }
    
private voidsetDownloadIn(int delayIndex)

        long delay = getDownloadDelay(delayIndex);
        long timeTillTrigger = 1000 * delay + SystemClock.elapsedRealtime();
        getAlarmManager().set(AlarmManager.ELAPSED_REALTIME, timeTillTrigger, mPacRefreshIntent);
    
private voidunbind()

        if (mConnection != null) {
            mContext.unbindService(mConnection);
            mConnection = null;
        }
        if (mProxyConnection != null) {
            mContext.unbindService(mProxyConnection);
            mProxyConnection = null;
        }
        mProxyService = null;
        mLastPort = -1;