Make PacProxyService be a system service

PacProxyInstaller class is running a thread all the time and is
listening to intent ACTION_PAC_REFRESH so it would be better to
make it be a system service with a manager class PacProxyManager
which is obtained with getSystemService(PacProxyManager.class).
Besides, rename PacProxyInstaller to PacProxyService will
be easier to know it's the service for PacProxyManager.

ConnectivityService is going to be a mainline module and it
needs constructor of PacProxyService to be SystemApi.
However, in current design, it needs to pass a handler and
an int arguments to the constructor which would be difficult
to maintain if just expose the constructor directly.

So, define a listener for the event that the current PAC
proxy has been installed so that the handler and the int
arguments can be removed from the constructor.

Bug: 177035719
Test: FrameworksNetTests
Change-Id: I2abff75ec59a17628ef006aad348c53fadbed076
This commit is contained in:
Aaron Huang 2021-01-18 15:28:01 +08:00
parent b4cbcf01aa
commit 5d31a15d84
14 changed files with 332 additions and 32 deletions

View File

@ -42,6 +42,16 @@ package android.net {
method @Nullable public byte[] getWatchlistConfigHash();
}
public class PacProxyManager {
method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void addPacProxyInstalledListener(@NonNull java.util.concurrent.Executor, @NonNull android.net.PacProxyManager.PacProxyInstalledListener);
method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void removePacProxyInstalledListener(@NonNull android.net.PacProxyManager.PacProxyInstalledListener);
method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void setCurrentProxyScriptUrl(@Nullable android.net.ProxyInfo);
}
public static interface PacProxyManager.PacProxyInstalledListener {
method public void onPacProxyInstalled(@Nullable android.net.Network, @NonNull android.net.ProxyInfo);
}
public final class Proxy {
method public static void setHttpProxyConfiguration(@Nullable android.net.ProxyInfo);
}

View File

@ -117,11 +117,13 @@ import android.net.EthernetManager;
import android.net.IEthernetManager;
import android.net.IIpSecService;
import android.net.INetworkPolicyManager;
import android.net.IPacProxyManager;
import android.net.IVpnManager;
import android.net.IpSecManager;
import android.net.NetworkPolicyManager;
import android.net.NetworkScoreManager;
import android.net.NetworkWatchlistManager;
import android.net.PacProxyManager;
import android.net.TetheringManager;
import android.net.VpnManager;
import android.net.lowpan.ILowpanManager;
@ -346,6 +348,15 @@ public final class SystemServiceRegistry {
// (which extends it).
SYSTEM_SERVICE_NAMES.put(android.text.ClipboardManager.class, Context.CLIPBOARD_SERVICE);
registerService(Context.PAC_PROXY_SERVICE, PacProxyManager.class,
new CachedServiceFetcher<PacProxyManager>() {
@Override
public PacProxyManager createService(ContextImpl ctx) throws ServiceNotFoundException {
IBinder b = ServiceManager.getServiceOrThrow(Context.PAC_PROXY_SERVICE);
IPacProxyManager service = IPacProxyManager.Stub.asInterface(b);
return new PacProxyManager(ctx.getOuterContext(), service);
}});
registerService(Context.NETD_SERVICE, IBinder.class, new StaticServiceFetcher<IBinder>() {
@Override
public IBinder createService() throws ServiceNotFoundException {

View File

@ -3451,6 +3451,7 @@ public abstract class Context {
VIBRATOR_SERVICE,
//@hide: STATUS_BAR_SERVICE,
CONNECTIVITY_SERVICE,
PAC_PROXY_SERVICE,
VCN_MANAGEMENT_SERVICE,
//@hide: IP_MEMORY_STORE_SERVICE,
IPSEC_SERVICE,
@ -4016,6 +4017,17 @@ public abstract class Context {
*/
public static final String CONNECTIVITY_SERVICE = "connectivity";
/**
* Use with {@link #getSystemService(String)} to retrieve a {@link
* android.net.PacProxyManager} for handling management of
* pac proxy information.
*
* @see #getSystemService(String)
* @see android.net.PacProxyManager
* @hide
*/
public static final String PAC_PROXY_SERVICE = "pac_proxy";
/**
* Use with {@link #getSystemService(String)} to retrieve a {@link android.net.vcn.VcnManager}
* for managing Virtual Carrier Networks

View File

@ -0,0 +1,25 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.net;
import android.net.Network;
import android.net.ProxyInfo;
/** {@hide} */
oneway interface IPacProxyInstalledListener {
void onPacProxyInstalled(in Network network, in ProxyInfo proxy);
}

View File

@ -0,0 +1,28 @@
/**
* Copyright (c) 2021, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing perNmissions and
* limitations under the License.
*/
package android.net;
import android.net.IPacProxyInstalledListener;
import android.net.ProxyInfo;
/** {@hide} */
interface IPacProxyManager
{
void addListener(IPacProxyInstalledListener listener);
void removeListener(IPacProxyInstalledListener listener);
void setCurrentProxyScriptUrl(in ProxyInfo proxyInfo);
}

View File

@ -0,0 +1,150 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.net;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.content.Context;
import android.os.Binder;
import android.os.RemoteException;
import com.android.internal.annotations.GuardedBy;
import java.util.HashMap;
import java.util.Objects;
import java.util.concurrent.Executor;
/**
* @hide
*/
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
@SystemService(Context.PAC_PROXY_SERVICE)
public class PacProxyManager {
private final Context mContext;
private final IPacProxyManager mService;
@GuardedBy("mListenerMap")
private final HashMap<PacProxyInstalledListener, PacProxyInstalledListenerProxy>
mListenerMap = new HashMap<>();
/** @hide */
public PacProxyManager(Context context, IPacProxyManager service) {
Objects.requireNonNull(service, "missing IPacProxyManager");
mContext = context;
mService = service;
}
/**
* Add a listener to start monitoring events reported by PacProxyService.
*/
@RequiresPermission(anyOf = {
android.Manifest.permission.NETWORK_STACK,
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
android.Manifest.permission.NETWORK_SETTINGS})
public void addPacProxyInstalledListener(@NonNull Executor executor,
@NonNull PacProxyInstalledListener listener) {
try {
synchronized (mListenerMap) {
final PacProxyInstalledListenerProxy listenerProxy =
new PacProxyInstalledListenerProxy(executor, listener);
if (null != mListenerMap.putIfAbsent(listener, listenerProxy)) {
throw new IllegalStateException("Listener is already added.");
}
mService.addListener(listenerProxy);
}
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Remove the listener to stop monitoring the event of PacProxyInstalledListener.
*/
@RequiresPermission(anyOf = {
android.Manifest.permission.NETWORK_STACK,
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
android.Manifest.permission.NETWORK_SETTINGS})
public void removePacProxyInstalledListener(@NonNull PacProxyInstalledListener listener) {
try {
synchronized (mListenerMap) {
final PacProxyInstalledListenerProxy listenerProxy = mListenerMap.remove(listener);
if (listenerProxy == null) return;
mService.removeListener(listenerProxy);
}
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Updates the PAC Proxy Installer with current Proxy information.
*/
@RequiresPermission(anyOf = {
android.Manifest.permission.NETWORK_STACK,
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
android.Manifest.permission.NETWORK_SETTINGS})
public void setCurrentProxyScriptUrl(@Nullable ProxyInfo proxy) {
try {
mService.setCurrentProxyScriptUrl(proxy);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* A callback interface for monitoring changes of PAC proxy information.
*/
public interface PacProxyInstalledListener {
/**
* Notify that the PAC proxy has been installed. Note that this method will be called with
* a ProxyInfo with an empty PAC URL when the PAC proxy is removed.
*
* This method supports different PAC proxies per-network but not all devices might support
* per-network proxies. In that case it will be applied globally.
*
* @param network the network for which this proxy installed.
* @param proxy the installed proxy.
*/
void onPacProxyInstalled(@Nullable Network network, @NonNull ProxyInfo proxy);
}
/**
* PacProxyInstalledListener proxy for PacProxyInstalledListener object.
* @hide
*/
public class PacProxyInstalledListenerProxy extends IPacProxyInstalledListener.Stub {
private final Executor mExecutor;
private final PacProxyInstalledListener mListener;
PacProxyInstalledListenerProxy(Executor executor, PacProxyInstalledListener listener) {
mExecutor = executor;
mListener = listener;
}
@Override
public void onPacProxyInstalled(Network network, ProxyInfo proxy) {
Binder.withCleanCallingIdentity(() -> {
mExecutor.execute(() -> {
mListener.onPacProxyInstalled(network, proxy);
});
});
}
}
}

View File

@ -51,7 +51,7 @@ public class PacProxySelector extends ProxySelector {
ServiceManager.getService(PROXY_SERVICE));
if (mProxyService == null) {
// Added because of b10267814 where mako is restarting.
Log.e(TAG, "PacProxyInstaller: no proxy service");
Log.e(TAG, "PacProxyService: no proxy service");
}
mDefaultList = Lists.newArrayList(java.net.Proxy.NO_PROXY);
}

View File

@ -129,7 +129,7 @@ public class ProxyInfo implements Parcelable {
}
/**
* Only used in PacProxyInstaller after Local Proxy is bound.
* Only used in PacProxyService after Local Proxy is bound.
* @hide
*/
public ProxyInfo(@NonNull Uri pacFileUrl, int localProxyPort) {

View File

@ -360,7 +360,7 @@ public class ProxyServer extends Thread {
try {
mCallback.setProxyPort(port);
} catch (RemoteException e) {
Log.w(TAG, "Proxy failed to report port to PacProxyInstaller", e);
Log.w(TAG, "Proxy failed to report port to PacProxyService", e);
}
}
mPort = port;
@ -371,7 +371,7 @@ public class ProxyServer extends Thread {
try {
callback.setProxyPort(mPort);
} catch (RemoteException e) {
Log.w(TAG, "Proxy failed to report port to PacProxyInstaller", e);
Log.w(TAG, "Proxy failed to report port to PacProxyService", e);
}
}
mCallback = callback;

View File

@ -30,7 +30,7 @@ public class ProxyService extends Service {
private static ProxyServer server = null;
/** Keep these values up-to-date with PacProxyInstaller.java */
/** Keep these values up-to-date with PacProxyService.java */
public static final String KEY_PROXY = "keyProxy";
public static final String HOST = "localhost";
public static final String EXCL_LIST = "";

View File

@ -4420,7 +4420,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
break;
}
case EVENT_PROXY_HAS_CHANGED: {
handleApplyDefaultProxy((ProxyInfo)msg.obj);
final Pair<Network, ProxyInfo> arg = (Pair<Network, ProxyInfo>) msg.obj;
handleApplyDefaultProxy(arg.second);
break;
}
case EVENT_REGISTER_NETWORK_PROVIDER: {

View File

@ -17,6 +17,7 @@
package com.android.server.connectivity;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.WorkerThread;
import android.app.AlarmManager;
import android.app.PendingIntent;
@ -27,12 +28,16 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.net.IPacProxyInstalledListener;
import android.net.IPacProxyManager;
import android.net.ProxyInfo;
import android.net.TrafficStats;
import android.net.Uri;
import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
@ -45,6 +50,7 @@ import com.android.internal.util.TrafficStatsConstants;
import com.android.net.IProxyCallback;
import com.android.net.IProxyPortListener;
import com.android.net.IProxyService;
import com.android.net.module.util.PermissionUtils;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@ -54,7 +60,7 @@ import java.net.URLConnection;
/**
* @hide
*/
public class PacProxyInstaller {
public class PacProxyService extends IPacProxyManager.Stub {
private static final String PAC_PACKAGE = "com.android.pacprocessor";
private static final String PAC_SERVICE = "com.android.pacprocessor.PacService";
private static final String PAC_SERVICE_NAME = "com.android.net.IProxyService";
@ -62,7 +68,7 @@ public class PacProxyInstaller {
private static final String PROXY_PACKAGE = "com.android.proxyhandler";
private static final String PROXY_SERVICE = "com.android.proxyhandler.ProxyService";
private static final String TAG = "PacProxyInstaller";
private static final String TAG = "PacProxyService";
private static final String ACTION_PAC_REFRESH = "android.net.proxy.PAC_REFRESH";
@ -90,8 +96,8 @@ public class PacProxyInstaller {
private volatile boolean mHasSentBroadcast;
private volatile boolean mHasDownloaded;
private final Handler mConnectivityHandler;
private final int mProxyMessage;
private final RemoteCallbackList<IPacProxyInstalledListener>
mCallbacks = new RemoteCallbackList<>();
/**
* Used for locking when setting mProxyService and all references to mCurrentPac.
@ -150,10 +156,10 @@ public class PacProxyInstaller {
}
}
public PacProxyInstaller(@NonNull Context context, @NonNull Handler handler, int proxyMessage) {
public PacProxyService(@NonNull Context context) {
mContext = context;
mLastPort = -1;
final HandlerThread netThread = new HandlerThread("android.pacproxyinstaller",
final HandlerThread netThread = new HandlerThread("android.pacproxyservice",
android.os.Process.THREAD_PRIORITY_DEFAULT);
netThread.start();
mNetThreadHandler = new Handler(netThread.getLooper());
@ -162,8 +168,6 @@ public class PacProxyInstaller {
context, 0, new Intent(ACTION_PAC_REFRESH), PendingIntent.FLAG_IMMUTABLE);
context.registerReceiver(new PacRefreshIntentReceiver(),
new IntentFilter(ACTION_PAC_REFRESH));
mConnectivityHandler = handler;
mProxyMessage = proxyMessage;
}
private AlarmManager getAlarmManager() {
@ -173,17 +177,35 @@ public class PacProxyInstaller {
return mAlarmManager;
}
@Override
public void addListener(IPacProxyInstalledListener listener) {
PermissionUtils.enforceNetworkStackPermissionOr(mContext,
android.Manifest.permission.NETWORK_SETTINGS);
mCallbacks.register(listener);
}
@Override
public void removeListener(IPacProxyInstalledListener listener) {
PermissionUtils.enforceNetworkStackPermissionOr(mContext,
android.Manifest.permission.NETWORK_SETTINGS);
mCallbacks.unregister(listener);
}
/**
* Updates the PAC Proxy Installer with current Proxy information. This is called by
* the ProxyTracker directly before a broadcast takes place to allow
* the PacProxyInstaller to indicate that the broadcast should not be sent and the
* PacProxyInstaller will trigger a new broadcast when it is ready.
* the ProxyTracker through PacProxyManager before a broadcast takes place to allow
* the PacProxyService to indicate that the broadcast should not be sent and the
* PacProxyService will trigger a new broadcast when it is ready.
*
* @param proxy Proxy information that is about to be broadcast.
*/
public void setCurrentProxyScriptUrl(@NonNull ProxyInfo proxy) {
@Override
public void setCurrentProxyScriptUrl(@Nullable ProxyInfo proxy) {
PermissionUtils.enforceNetworkStackPermissionOr(mContext,
android.Manifest.permission.NETWORK_SETTINGS);
synchronized (mBroadcastStateLock) {
if (!Uri.EMPTY.equals(proxy.getPacFileUrl())) {
if (proxy != null && !Uri.EMPTY.equals(proxy.getPacFileUrl())) {
if (proxy.getPacFileUrl().equals(mPacUrl) && (proxy.getPort() > 0)) return;
mPacUrl = proxy.getPacFileUrl();
mCurrentDelay = DELAY_1;
@ -369,8 +391,9 @@ public class PacProxyInstaller {
}
}
};
mContext.bindService(intent, mProxyConnection,
Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND | Context.BIND_NOT_VISIBLE);
mContext.bindService(intent,
Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND | Context.BIND_NOT_VISIBLE,
new HandlerExecutor(mNetThreadHandler), mProxyConnection);
}
private void unbind() {
@ -387,9 +410,19 @@ public class PacProxyInstaller {
}
private void sendPacBroadcast(ProxyInfo proxy) {
mConnectivityHandler.sendMessage(mConnectivityHandler.obtainMessage(mProxyMessage, proxy));
final int length = mCallbacks.beginBroadcast();
for (int i = 0; i < length; i++) {
final IPacProxyInstalledListener listener = mCallbacks.getBroadcastItem(i);
if (listener != null) {
try {
listener.onPacProxyInstalled(null /* network */, proxy);
} catch (RemoteException ignored) { }
}
}
mCallbacks.finishBroadcast();
}
// This method must be called on mNetThreadHandler.
private void sendProxyIfNeeded() {
synchronized (mBroadcastStateLock) {
if (!mHasDownloaded || (mLastPort == -1)) {

View File

@ -27,15 +27,19 @@ import android.annotation.Nullable;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.net.Network;
import android.net.PacProxyManager;
import android.net.Proxy;
import android.net.ProxyInfo;
import android.net.Uri;
import android.os.Binder;
import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.UserHandle;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
import com.android.internal.annotations.GuardedBy;
import com.android.net.module.util.ProxyUtils;
@ -67,7 +71,7 @@ public class ProxyTracker {
// is not set. Individual networks have their own settings that override this. This member
// is set through setDefaultProxy, which is called when the default network changes proxies
// in its LinkProperties, or when ConnectivityService switches to a new default network, or
// when PacProxyInstaller resolves the proxy.
// when PacProxyService resolves the proxy.
@Nullable
@GuardedBy("mProxyLock")
private volatile ProxyInfo mDefaultProxy = null;
@ -77,16 +81,31 @@ public class ProxyTracker {
private final Handler mConnectivityServiceHandler;
// The object responsible for Proxy Auto Configuration (PAC).
@NonNull
private final PacProxyInstaller mPacProxyInstaller;
private final PacProxyManager mPacProxyManager;
private class PacProxyInstalledListener implements PacProxyManager.PacProxyInstalledListener {
private final int mEvent;
PacProxyInstalledListener(int event) {
mEvent = event;
}
public void onPacProxyInstalled(@Nullable Network network, @NonNull ProxyInfo proxy) {
mConnectivityServiceHandler
.sendMessage(mConnectivityServiceHandler
.obtainMessage(mEvent, new Pair<>(network, proxy)));
}
}
public ProxyTracker(@NonNull final Context context,
@NonNull final Handler connectivityServiceInternalHandler, final int pacChangedEvent) {
mContext = context;
mConnectivityServiceHandler = connectivityServiceInternalHandler;
mPacProxyInstaller = new PacProxyInstaller(
context, connectivityServiceInternalHandler, pacChangedEvent);
mPacProxyManager = context.getSystemService(PacProxyManager.class);
PacProxyInstalledListener listener = new PacProxyInstalledListener(pacChangedEvent);
mPacProxyManager.addPacProxyInstalledListener(
new HandlerExecutor(mConnectivityServiceHandler), listener);
}
// Convert empty ProxyInfo's to null as null-checks are used to determine if proxies are present
@ -182,7 +201,7 @@ public class ProxyTracker {
if (!TextUtils.isEmpty(pacFileUrl)) {
mConnectivityServiceHandler.post(
() -> mPacProxyInstaller.setCurrentProxyScriptUrl(proxyProperties));
() -> mPacProxyManager.setCurrentProxyScriptUrl(proxyProperties));
}
}
}
@ -226,7 +245,7 @@ public class ProxyTracker {
final ProxyInfo defaultProxy = getDefaultProxy();
final ProxyInfo proxyInfo = null != defaultProxy ?
defaultProxy : ProxyInfo.buildDirectProxy("", 0, Collections.emptyList());
mPacProxyInstaller.setCurrentProxyScriptUrl(proxyInfo);
mPacProxyManager.setCurrentProxyScriptUrl(proxyInfo);
if (!shouldSendBroadcast(proxyInfo)) {
return;
@ -312,10 +331,10 @@ public class ProxyTracker {
return;
}
// This call could be coming from the PacProxyInstaller, containing the port of the
// This call could be coming from the PacProxyService, containing the port of the
// local proxy. If this new proxy matches the global proxy then copy this proxy to the
// global (to get the correct local port), and send a broadcast.
// TODO: Switch PacProxyInstaller to have its own message to send back rather than
// TODO: Switch PacProxyService to have its own message to send back rather than
// reusing EVENT_HAS_CHANGED_PROXY and this call to handleApplyDefaultProxy.
if ((mGlobalProxy != null) && (proxyInfo != null)
&& (!Uri.EMPTY.equals(proxyInfo.getPacFileUrl()))

View File

@ -108,6 +108,7 @@ import com.android.server.camera.CameraServiceProxy;
import com.android.server.clipboard.ClipboardService;
import com.android.server.compat.PlatformCompat;
import com.android.server.compat.PlatformCompatNative;
import com.android.server.connectivity.PacProxyService;
import com.android.server.contentcapture.ContentCaptureManagerInternal;
import com.android.server.coverage.CoverageService;
import com.android.server.devicepolicy.DevicePolicyManagerService;
@ -1115,6 +1116,7 @@ public final class SystemServer {
ConsumerIrService consumerIr = null;
MmsServiceBroker mmsService = null;
HardwarePropertiesManagerService hardwarePropertiesService = null;
PacProxyService pacProxyService = null;
boolean disableSystemTextClassifier = SystemProperties.getBoolean(
"config.disable_systemtextclassifier", false);
@ -1623,6 +1625,15 @@ public final class SystemServer {
t.traceEnd();
}
t.traceBegin("StartPacProxyService");
try {
pacProxyService = new PacProxyService(context);
ServiceManager.addService(Context.PAC_PROXY_SERVICE, pacProxyService);
} catch (Throwable e) {
reportWtf("starting PacProxyService", e);
}
t.traceEnd();
t.traceBegin("StartConnectivityService");
// This has to be called after NetworkManagementService, NetworkStatsService
// and NetworkPolicyManager because ConnectivityService needs to take these