1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.net; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.annotation.RequiresPermission; 22 import android.annotation.SystemApi; 23 import android.annotation.SystemService; 24 import android.content.Context; 25 import android.os.Binder; 26 import android.os.RemoteException; 27 28 import com.android.internal.annotations.GuardedBy; 29 30 import java.util.HashMap; 31 import java.util.Objects; 32 import java.util.concurrent.Executor; 33 34 /** 35 * @hide 36 */ 37 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 38 @SystemService(Context.PAC_PROXY_SERVICE) 39 public class PacProxyManager { 40 private final Context mContext; 41 private final IPacProxyManager mService; 42 @GuardedBy("mListenerMap") 43 private final HashMap<PacProxyInstalledListener, PacProxyInstalledListenerProxy> 44 mListenerMap = new HashMap<>(); 45 46 /** @hide */ PacProxyManager(Context context, IPacProxyManager service)47 public PacProxyManager(Context context, IPacProxyManager service) { 48 Objects.requireNonNull(service, "missing IPacProxyManager"); 49 mContext = context; 50 mService = service; 51 } 52 53 /** 54 * Add a listener to start monitoring events reported by PacProxyService. 55 */ 56 @RequiresPermission(anyOf = { 57 android.Manifest.permission.NETWORK_STACK, 58 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, 59 android.Manifest.permission.NETWORK_SETTINGS}) addPacProxyInstalledListener(@onNull Executor executor, @NonNull PacProxyInstalledListener listener)60 public void addPacProxyInstalledListener(@NonNull Executor executor, 61 @NonNull PacProxyInstalledListener listener) { 62 try { 63 synchronized (mListenerMap) { 64 final PacProxyInstalledListenerProxy listenerProxy = 65 new PacProxyInstalledListenerProxy(executor, listener); 66 67 if (null != mListenerMap.putIfAbsent(listener, listenerProxy)) { 68 throw new IllegalStateException("Listener is already added."); 69 } 70 mService.addListener(listenerProxy); 71 } 72 } catch (RemoteException e) { 73 throw e.rethrowFromSystemServer(); 74 } 75 } 76 77 /** 78 * Remove the listener to stop monitoring the event of PacProxyInstalledListener. 79 */ 80 @RequiresPermission(anyOf = { 81 android.Manifest.permission.NETWORK_STACK, 82 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, 83 android.Manifest.permission.NETWORK_SETTINGS}) removePacProxyInstalledListener(@onNull PacProxyInstalledListener listener)84 public void removePacProxyInstalledListener(@NonNull PacProxyInstalledListener listener) { 85 try { 86 synchronized (mListenerMap) { 87 final PacProxyInstalledListenerProxy listenerProxy = mListenerMap.remove(listener); 88 if (listenerProxy == null) return; 89 mService.removeListener(listenerProxy); 90 } 91 } catch (RemoteException e) { 92 throw e.rethrowFromSystemServer(); 93 } 94 } 95 96 /** 97 * Updates the PAC Proxy Service with current Proxy information. 98 */ 99 @RequiresPermission(anyOf = { 100 android.Manifest.permission.NETWORK_STACK, 101 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, 102 android.Manifest.permission.NETWORK_SETTINGS}) setCurrentProxyScriptUrl(@ullable ProxyInfo proxy)103 public void setCurrentProxyScriptUrl(@Nullable ProxyInfo proxy) { 104 try { 105 mService.setCurrentProxyScriptUrl(proxy); 106 } catch (RemoteException e) { 107 throw e.rethrowFromSystemServer(); 108 } 109 } 110 111 /** 112 * A callback interface for monitoring changes of PAC proxy information. 113 */ 114 public interface PacProxyInstalledListener { 115 /** 116 * Notify that the PAC proxy has been installed. Note that this method will be called with 117 * a ProxyInfo with an empty PAC URL when the PAC proxy is removed. 118 * 119 * This method supports different PAC proxies per-network but not all devices might support 120 * per-network proxies. In that case it will be applied globally. 121 * 122 * @param network the network for which this proxy installed. 123 * @param proxy the installed proxy. 124 */ onPacProxyInstalled(@ullable Network network, @NonNull ProxyInfo proxy)125 void onPacProxyInstalled(@Nullable Network network, @NonNull ProxyInfo proxy); 126 } 127 128 /** 129 * PacProxyInstalledListener proxy for PacProxyInstalledListener object. 130 * @hide 131 */ 132 public class PacProxyInstalledListenerProxy extends IPacProxyInstalledListener.Stub { 133 private final Executor mExecutor; 134 private final PacProxyInstalledListener mListener; 135 PacProxyInstalledListenerProxy(Executor executor, PacProxyInstalledListener listener)136 PacProxyInstalledListenerProxy(Executor executor, PacProxyInstalledListener listener) { 137 mExecutor = executor; 138 mListener = listener; 139 } 140 141 @Override onPacProxyInstalled(Network network, ProxyInfo proxy)142 public void onPacProxyInstalled(Network network, ProxyInfo proxy) { 143 Binder.withCleanCallingIdentity(() -> { 144 mExecutor.execute(() -> { 145 mListener.onPacProxyInstalled(network, proxy); 146 }); 147 }); 148 } 149 } 150 } 151