1 /* 2 * Copyright (C) 2020 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 com.android.cts.deviceowner.proxy; 18 19 import android.content.BroadcastReceiver; 20 import android.content.Context; 21 import android.content.Intent; 22 import android.content.IntentFilter; 23 import android.net.ProxyInfo; 24 import android.net.Uri; 25 import android.text.TextUtils; 26 import android.util.Log; 27 28 import com.android.cts.deviceowner.BaseDeviceOwnerTest; 29 30 import java.net.Proxy; 31 import java.util.ArrayList; 32 import java.util.List; 33 import java.util.concurrent.Semaphore; 34 import java.util.concurrent.TimeUnit; 35 36 public class BaseProxyTest extends BaseDeviceOwnerTest { 37 static final String TAG = "ProxyCtsTest"; 38 protected static final int TIME_OUT_SECS = 10; 39 40 protected ProxyInfo mProxy; 41 protected String mProxyHost = "localhost"; 42 43 private ProxyBroadcastReceiver mReceiver; 44 45 @Override setUp()46 protected void setUp() throws Exception { 47 super.setUp(); 48 // Register a broadcast receiver and wait for the first sticky broadcast to come in. 49 registerAndWaitForStickyBroadcast(); 50 51 if (isProxyStatic() || isProxyPac()) { 52 // If there is a proxy set, try to clear it so we can test properly. 53 // If we can't clear it then we can't run the test. 54 assertTrue("No broadcast after clearing proxy.", clearProxyAndWaitForBroadcast()); 55 waitForClearProxySysProp(); 56 } 57 } 58 registerAndWaitForStickyBroadcast()59 private void registerAndWaitForStickyBroadcast() throws Exception { 60 mReceiver = new ProxyBroadcastReceiver(); 61 mContext.registerReceiver(mReceiver, 62 new IntentFilter(android.net.Proxy.PROXY_CHANGE_ACTION)); 63 // don't assert the outcome, as there might not be a sticky broadcast yet, when this is run 64 // for the first time after a reboot 65 mReceiver.waitForBroadcast(); 66 } 67 68 @Override tearDown()69 protected void tearDown() throws Exception { 70 Log.d(TAG, "tearDown"); 71 // Do not assert the outcome, as there will be no broadcast if clear proxy is performed while 72 // the system has no proxy configured. 73 clearProxyAndWaitForBroadcast(); 74 waitForClearProxySysProp(); 75 mContext.unregisterReceiver(mReceiver); 76 super.tearDown(); 77 } 78 79 /** 80 * Set the global proxy. 81 */ setProxyAndWaitForBroadcast(ProxyInfo proxy)82 protected boolean setProxyAndWaitForBroadcast(ProxyInfo proxy) throws Exception { 83 Log.d(TAG, "setProxyAndWaitForBroadcast(), setting Proxy to " + proxy); 84 mDevicePolicyManager.setRecommendedGlobalProxy(getWho(), proxy); 85 return mReceiver.waitForBroadcast(); 86 } 87 88 /** 89 * Clear the global proxy. 90 */ clearProxyAndWaitForBroadcast()91 protected boolean clearProxyAndWaitForBroadcast() throws Exception { 92 return setProxyAndWaitForBroadcast(null); 93 } 94 isProxyEmpty()95 protected boolean isProxyEmpty() { 96 return (mProxy == null) || (TextUtils.isEmpty(mProxy.getHost()) 97 && (mProxy.getPacFileUrl() == Uri.EMPTY)); 98 } 99 isProxyStatic()100 protected boolean isProxyStatic() { 101 return (mProxy != null) && !TextUtils.isEmpty(mProxy.getHost()); 102 } 103 isProxyPac()104 private boolean isProxyPac() { 105 return (mProxy != null) && (mProxy.getPacFileUrl() != Uri.EMPTY); 106 } 107 isCorrectPacProxy(Uri pacUri)108 protected boolean isCorrectPacProxy(Uri pacUri) { 109 return isProxyPac() && pacUri.equals(mProxy.getPacFileUrl()); 110 } 111 112 /** 113 * Check if the java proxy property is set correctly. 114 */ isProxySysPropSet()115 private boolean isProxySysPropSet() { 116 String proxy = System.getProperty("http.proxyHost"); 117 return (proxy != null) && proxy.equals(mProxyHost); 118 } 119 120 // Since this is a java system property there is no good way to wait for 121 // this other than to poll for it to be the correct value. waitForSetProxySysProp()122 protected void waitForSetProxySysProp() { 123 int ct = 0; 124 while (!isProxySysPropSet() && (++ct < (TIME_OUT_SECS * 10))) { 125 try { 126 Thread.sleep(100); 127 } catch (InterruptedException e) { 128 } 129 } 130 assertTrue("Timed out waiting for proxy to set", isProxySysPropSet()); 131 } 132 133 /** 134 * Check if the java proxy property is clear. 135 */ isProxySysPropClear()136 private boolean isProxySysPropClear() { 137 return TextUtils.isEmpty(System.getProperty("http.proxyHost")); 138 } 139 140 // Since this is a java system property there is no good way to wait for 141 // this other than to poll for it to be the correct value. waitForClearProxySysProp()142 protected void waitForClearProxySysProp() { 143 int ct = 0; 144 while (!isProxySysPropClear() && (++ct < (TIME_OUT_SECS * 10))) { 145 try { 146 Thread.sleep(100); 147 } catch (InterruptedException e) { 148 } 149 } 150 assertTrue("Timed out waiting for proxy to clear", isProxySysPropClear()); 151 } 152 153 // Utility function. newArrayList(Proxy... proxies)154 protected List<Proxy> newArrayList(Proxy... proxies) { 155 List<Proxy> ret = new ArrayList<Proxy>(); 156 for (Proxy p : proxies) { 157 ret.add(p); 158 } 159 return ret; 160 } 161 162 private class ProxyBroadcastReceiver extends BroadcastReceiver { 163 private final Semaphore mSemaphore = new Semaphore(0); 164 165 @Override onReceive(Context context, Intent intent)166 public void onReceive(Context context, Intent intent) { 167 mProxy = intent.getParcelableExtra(android.net.Proxy.EXTRA_PROXY_INFO); 168 Log.d(TAG, "Proxy received " + mProxy); 169 mSemaphore.release(); 170 } 171 waitForBroadcast()172 public boolean waitForBroadcast() throws Exception { 173 if (mSemaphore.tryAcquire(10, TimeUnit.SECONDS)) { 174 return true; 175 } 176 return false; 177 } 178 } 179 } 180