From 9ced3cd9d6ea414523051ec872fffc68f5fdbf08 Mon Sep 17 00:00:00 2001 From: Jason Monk Date: Mon, 12 Aug 2013 16:42:38 -0400 Subject: [PATCH] Change PacProcessor to Android Service This switches the PacProcessor over to an Android Service. The service is bound and unbound by the PacManager, which also adds it to the ServiceManager, allowing for Context-Free access by the PacProxySelector in all DVMs. bug:10182711 Change-Id: Id1ff7660be56e8976cdcccd76e041feb47a17a61 --- Android.mk | 2 +- CleanSpec.mk | 1 + core/java/android/net/PacProxySelector.java | 26 ++- core/java/android/net/Proxy.java | 8 +- core/res/AndroidManifest.xml | 1 + packages/services/PacProcessor/Android.mk | 27 +-- packages/services/PacProcessor/AndroidManifest.xml | 16 ++ packages/services/PacProcessor/IProxyService.cpp | 97 --------- packages/services/PacProcessor/IProxyService.h | 59 ------ packages/services/PacProcessor/ProxyService.cpp | 96 --------- packages/services/PacProcessor/ProxyService.h | 33 --- .../com/android/net/IProxyService.aidl | 27 +++ packages/services/PacProcessor/jni/Android.mk | 41 ++++ .../jni/com_android_pacprocessor_PacNative.cpp | 148 +++++++++++++ packages/services/PacProcessor/jni/jni_init.cpp | 38 ++++ packages/services/PacProcessor/main_pacserver.cpp | 43 ---- .../services/PacProcessor/res/values/strings.xml | 6 + .../src/com/android/pacprocessor/PacNative.java | 86 ++++++++ .../src/com/android/pacprocessor/PacService.java | 101 +++++++++ .../Proxy/com/android/net/IProxyService.aidl | 16 -- .../android/server/connectivity/PacManager.java | 230 ++++++++++++--------- 21 files changed, 634 insertions(+), 468 deletions(-) create mode 100644 packages/services/PacProcessor/AndroidManifest.xml delete mode 100644 packages/services/PacProcessor/IProxyService.cpp delete mode 100644 packages/services/PacProcessor/IProxyService.h delete mode 100644 packages/services/PacProcessor/ProxyService.cpp delete mode 100644 packages/services/PacProcessor/ProxyService.h create mode 100644 packages/services/PacProcessor/com/android/net/IProxyService.aidl create mode 100644 packages/services/PacProcessor/jni/Android.mk create mode 100644 packages/services/PacProcessor/jni/com_android_pacprocessor_PacNative.cpp create mode 100644 packages/services/PacProcessor/jni/jni_init.cpp delete mode 100644 packages/services/PacProcessor/main_pacserver.cpp create mode 100644 packages/services/PacProcessor/res/values/strings.xml create mode 100644 packages/services/PacProcessor/src/com/android/pacprocessor/PacNative.java create mode 100644 packages/services/PacProcessor/src/com/android/pacprocessor/PacService.java delete mode 100644 packages/services/Proxy/com/android/net/IProxyService.aidl diff --git a/Android.mk b/Android.mk index 656e40c2cba2..73f4048cd2d8 100644 --- a/Android.mk +++ b/Android.mk @@ -264,7 +264,7 @@ LOCAL_SRC_FILES += \ telephony/java/com/android/internal/telephony/IWapPushManager.aidl \ wifi/java/android/net/wifi/IWifiManager.aidl \ wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl \ - packages/services/Proxy/com/android/net/IProxyService.aidl \ + packages/services/PacProcessor/com/android/net/IProxyService.aidl \ # FRAMEWORKS_BASE_JAVA_SRC_DIRS comes from build/core/pathmap.mk LOCAL_AIDL_INCLUDES += $(FRAMEWORKS_BASE_JAVA_SRC_DIRS) diff --git a/CleanSpec.mk b/CleanSpec.mk index 8fd5186c67e4..a94252d66ec2 100644 --- a/CleanSpec.mk +++ b/CleanSpec.mk @@ -170,6 +170,7 @@ $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framew $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/core/java/android/print/IPrinterDiscoveryObserver.*) $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/core/java/android/print/) $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/core/java/android/printservice/) +$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/packages/services/Proxy/) # ************************************************ # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST # ************************************************ diff --git a/core/java/android/net/PacProxySelector.java b/core/java/android/net/PacProxySelector.java index d3ce2e509e14..b674324197ed 100644 --- a/core/java/android/net/PacProxySelector.java +++ b/core/java/android/net/PacProxySelector.java @@ -1,3 +1,18 @@ +/* + * Copyright (C) 2013 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; @@ -25,19 +40,25 @@ public class PacProxySelector extends ProxySelector { private static final String TAG = "PacProxySelector"; public static final String PROXY_SERVICE = "com.android.net.IProxyService"; private IProxyService mProxyService; + private final List mDefaultList; public PacProxySelector() { mProxyService = IProxyService.Stub.asInterface( ServiceManager.getService(PROXY_SERVICE)); if (mProxyService == null) { // Added because of b10267814 where mako is restarting. - Log.e(TAG, "PackManager: no proxy service"); + Log.e(TAG, "PacManager: no proxy service"); } + mDefaultList = Lists.newArrayList(java.net.Proxy.NO_PROXY); } @Override public List select(URI uri) { if (mProxyService == null) { + mProxyService = IProxyService.Stub.asInterface( + ServiceManager.getService(PROXY_SERVICE)); + } + if (mProxyService == null) { Log.e(TAG, "select: no proxy service return NO_PROXY"); return Lists.newArrayList(java.net.Proxy.NO_PROXY); } @@ -53,6 +74,9 @@ public class PacProxySelector extends ProxySelector { } catch (RemoteException e) { e.printStackTrace(); } + if (response == null) { + return mDefaultList; + } return parseResponse(response); } diff --git a/core/java/android/net/Proxy.java b/core/java/android/net/Proxy.java index 5b38f5793a74..c3e14381f3af 100644 --- a/core/java/android/net/Proxy.java +++ b/core/java/android/net/Proxy.java @@ -48,7 +48,6 @@ public final class Proxy { private static final String TAG = "Proxy"; private static final ProxySelector sDefaultProxySelector; - private static PacProxySelector sPacProxySelector; /** * Used to notify an app that's caching the default connection proxy @@ -352,11 +351,8 @@ public final class Proxy { System.clearProperty("http.nonProxyHosts"); System.clearProperty("https.nonProxyHosts"); } - if ((pacFileUrl != null) && !TextUtils.isEmpty(pacFileUrl)) { - if (sPacProxySelector == null) { - sPacProxySelector = new PacProxySelector(); - } - ProxySelector.setDefault(sPacProxySelector); + if (!TextUtils.isEmpty(pacFileUrl)) { + ProxySelector.setDefault(new PacProxySelector()); } else { ProxySelector.setDefault(sDefaultProxySelector); } diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 1363e3ca2a5a..813b55f14beb 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -218,6 +218,7 @@ + diff --git a/packages/services/PacProcessor/Android.mk b/packages/services/PacProcessor/Android.mk index e4afde69eb22..d9566d5022d1 100644 --- a/packages/services/PacProcessor/Android.mk +++ b/packages/services/PacProcessor/Android.mk @@ -18,24 +18,15 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) -LOCAL_SRC_FILES := \ - main_pacserver.cpp \ - ProxyService.cpp \ - IProxyService.cpp - -LOCAL_C_INCLUDES += \ - external/chromium-libpac/src - -LOCAL_SHARED_LIBRARIES := \ - libutils \ - liblog \ - libpac \ - libbinder \ - libstlport - -LOCAL_MODULE := pacserver LOCAL_MODULE_TAGS := optional -include external/stlport/libstlport.mk +LOCAL_SRC_FILES := $(call all-java-files-under, src) -include $(BUILD_EXECUTABLE) +LOCAL_PACKAGE_NAME := PacProcessor +LOCAL_CERTIFICATE := platform + +LOCAL_REQUIRED_MODULES := libjni_pacprocessor + +include $(BUILD_PACKAGE) + +include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/packages/services/PacProcessor/AndroidManifest.xml b/packages/services/PacProcessor/AndroidManifest.xml new file mode 100644 index 000000000000..6740c169ff21 --- /dev/null +++ b/packages/services/PacProcessor/AndroidManifest.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + diff --git a/packages/services/PacProcessor/IProxyService.cpp b/packages/services/PacProcessor/IProxyService.cpp deleted file mode 100644 index 3707d8554b34..000000000000 --- a/packages/services/PacProcessor/IProxyService.cpp +++ /dev/null @@ -1,97 +0,0 @@ -#define LOG_TAG "ProxyTesting" - -#include -#include -#include -#include -#include -#include "IProxyService.h" - -#include - -#include - -using namespace android; - -String16 BpProxyService::resolveProxies(String16 host, String16 url) { - String16 ret; - return ret; -} - -void BpProxyService::setPacFile(String16& scriptContents) { - -} - -void BpProxyService::startPacSystem() { - -} -void BpProxyService::stopPacSystem() { - -} - -IMPLEMENT_META_INTERFACE(ProxyService, "com.android.net.IProxyService"); - -status_t BnProxyService::onTransact( - uint32_t code, const Parcel& data, - Parcel* reply, uint32_t flags) { - int returnInt = 0; - switch (code) { - case RESOLVE_PROXIES: - { - CHECK_INTERFACE(IProxyService, data, reply); - String16 host = data.readString16(); - String16 url = data.readString16(); - String16 response = resolveProxies(host, url); - reply->writeNoException(); - reply->writeString16(response); - return NO_ERROR; - } break; - case SET_PAC: - { - CHECK_INTERFACE(IProxyService, data, reply); - if (notSystemUid()) { - returnInt = 1; - } else { - String16 pacFile = data.readString16(); - setPacFile(pacFile); - } - reply->writeNoException(); - reply->writeInt32(returnInt); - return NO_ERROR; - } break; - case START_PAC: - { - CHECK_INTERFACE(IProxyService, data, reply); - if (notSystemUid()) { - returnInt = 1; - } else { - startPacSystem(); - } - reply->writeNoException(); - reply->writeInt32(returnInt); - return NO_ERROR; - } break; - case STOP_PAC: - { - CHECK_INTERFACE(IProxyService, data, reply); - if (notSystemUid()) { - returnInt = 1; - } else { - stopPacSystem(); - } - reply->writeNoException(); - reply->writeInt32(returnInt); - return NO_ERROR; - } break; - default: - return BBinder::onTransact(code, data, reply, flags); - } -} - -int BnProxyService::getCallingUid() { - return IPCThreadState::self()->getCallingUid(); -} - -bool BnProxyService::notSystemUid() { - return getCallingUid() != AID_SYSTEM; -} diff --git a/packages/services/PacProcessor/IProxyService.h b/packages/services/PacProcessor/IProxyService.h deleted file mode 100644 index 57c527b5944e..000000000000 --- a/packages/services/PacProcessor/IProxyService.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef IPROXY_SERVICE_H -#define IPROXY_SERVICE_H - -#include -#include - -namespace android { -class IProxyService : public IInterface { -public: - /** - * Keep up-to-date with - * frameworks/base/packages/services/Proxy/com/android/net/IProxyService.aidl - */ - enum { - RESOLVE_PROXIES = IBinder::FIRST_CALL_TRANSACTION, - SET_PAC, - START_PAC, - STOP_PAC, - }; -public: - DECLARE_META_INTERFACE(ProxyService); - -public: - - virtual String16 resolveProxies(String16 host, String16 url) = 0; - - virtual void setPacFile(String16& scriptContents) = 0; - - virtual void startPacSystem() = 0; - virtual void stopPacSystem() = 0; -private: -}; - -class BpProxyService : public BpInterface { -public: - BpProxyService(const sp& impl) : BpInterface(impl) {} - - virtual String16 resolveProxies(String16 host, String16 url); - - virtual void setPacFile(String16& scriptContents); - - virtual void startPacSystem(); - virtual void stopPacSystem(); -}; - -class BnProxyService : public BnInterface { -public: - virtual status_t onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0); - -private: - int getCallingUid(); - - bool notSystemUid(); -}; -} - - -#endif //IPROXY_SERVICE_H diff --git a/packages/services/PacProcessor/ProxyService.cpp b/packages/services/PacProcessor/ProxyService.cpp deleted file mode 100644 index 7084a47fe435..000000000000 --- a/packages/services/PacProcessor/ProxyService.cpp +++ /dev/null @@ -1,96 +0,0 @@ -#define LOG_TAG "ProxyService" -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "ProxyService.h" - -using namespace net; - -using namespace android; - -class ProxyErrorLogger : public ProxyErrorListener { -protected: - ~ProxyErrorLogger() { - - } -public: - void AlertMessage(String16 message) { - String8 str(message); - ALOGD("Alert: %s", str.string()); - } - void ErrorMessage(String16 message) { - String8 str(message); - ALOGE("Error: %s", str.string()); - } -}; - -void ProxyService::instantiate() { - ALOGV("instantiate"); - defaultServiceManager()->addService(String16("com.android.net.IProxyService"), - new ProxyService()); -} - -ProxyService::ProxyService() { - hasSetScript = false; -} - -ProxyService::~ProxyService() { - stopPacSystem(); -} - -String16 ProxyService::resolveProxies(String16 host, String16 url) { - ALOGV("resolve"); - String16 blankRet; - if (proxyResolver != NULL) { - if (hasSetScript) { - String16 ret; - if (proxyResolver->GetProxyForURL(url, host, &ret) != OK) { - return blankRet; - } - return ret; - } else { - ALOGD("Unable to resolve PAC when no script is set!"); - } - } else { - ALOGE("Cannot parse while resolver not initialized!"); - } - return blankRet; -} - -void ProxyService::setPacFile(String16& scriptContents) { - ALOGV("set"); - if (proxyResolver != NULL) { - if (proxyResolver->SetPacScript(scriptContents) != OK) { - ALOGD("Unable to initialize PAC - Resolving will not work"); - } else { - hasSetScript = true; - } - } else { - ALOGE("PAC script set while resolver not initialized!"); - } -} - -void ProxyService::startPacSystem() { - ALOGV("start"); - // Stop in case redundant start call - stopPacSystem(); - - proxyResolver = new ProxyResolverV8(ProxyResolverJSBindings::CreateDefault(), - new ProxyErrorLogger()); - hasSetScript = false; -} - -void ProxyService::stopPacSystem() { - ALOGV("stop"); - if (proxyResolver != NULL) { - delete proxyResolver; - proxyResolver = NULL; - } -} diff --git a/packages/services/PacProcessor/ProxyService.h b/packages/services/PacProcessor/ProxyService.h deleted file mode 100644 index a0861b2d620e..000000000000 --- a/packages/services/PacProcessor/ProxyService.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef PROXY_SERVICE_H -#define PROXY_SERVICE_H - -#include -#include "IProxyService.h" -#include "proxy_resolver_v8.h" - -namespace android { - -class ProxyService : public BnProxyService { -public: - static void instantiate(); - -private: - ProxyService(); - virtual ~ProxyService(); - -public: - String16 resolveProxies(String16 host, String16 url); - - void setPacFile(String16& scriptContents); - - void startPacSystem(); - void stopPacSystem(); - -private: - net::ProxyResolverV8* proxyResolver; - bool hasSetScript; -}; - -} - -#endif //PROXY_SERVICE_H diff --git a/packages/services/PacProcessor/com/android/net/IProxyService.aidl b/packages/services/PacProcessor/com/android/net/IProxyService.aidl new file mode 100644 index 000000000000..4e54aba5c3bf --- /dev/null +++ b/packages/services/PacProcessor/com/android/net/IProxyService.aidl @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2013, 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 com.android.net; + +/** @hide */ +interface IProxyService +{ + String resolvePacFile(String host, String url); + + oneway void setPacFile(String scriptContents); + + oneway void startPacSystem(); + oneway void stopPacSystem(); +} diff --git a/packages/services/PacProcessor/jni/Android.mk b/packages/services/PacProcessor/jni/Android.mk new file mode 100644 index 000000000000..f16c90b367dd --- /dev/null +++ b/packages/services/PacProcessor/jni/Android.mk @@ -0,0 +1,41 @@ +# +# Copyright (C) 2013 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. +# + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + jni_init.cpp \ + com_android_pacprocessor_PacNative.cpp + +LOCAL_C_INCLUDES += \ + external/chromium-libpac/src + +LOCAL_SHARED_LIBRARIES := \ + libandroidfw \ + libandroid_runtime \ + liblog \ + libutils \ + libnativehelper \ + libpac + +LOCAL_MODULE := libjni_pacprocessor +LOCAL_MODULE_TAGS := optional + +include external/stlport/libstlport.mk + +include $(BUILD_SHARED_LIBRARY) diff --git a/packages/services/PacProcessor/jni/com_android_pacprocessor_PacNative.cpp b/packages/services/PacProcessor/jni/com_android_pacprocessor_PacNative.cpp new file mode 100644 index 000000000000..c5aa13bb26eb --- /dev/null +++ b/packages/services/PacProcessor/jni/com_android_pacprocessor_PacNative.cpp @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2013 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. + */ + +#define LOG_TAG "PacProcessor" + +#include +#include +#include "android_runtime/AndroidRuntime.h" + +#include "jni.h" +#include "JNIHelp.h" + +#include "proxy_resolver_v8.h" + +namespace android { + +class ProxyErrorLogger : public net::ProxyErrorListener { +public: + ~ProxyErrorLogger() { + + } + void AlertMessage(String16 message) { + String8 str(message); + ALOGD("Alert: %s", str.string()); + } + void ErrorMessage(String16 message) { + String8 str(message); + ALOGE("Error: %s", str.string()); + } +}; + +net::ProxyResolverV8* proxyResolver = NULL; +ProxyErrorLogger* logger = NULL; +bool pacSet = false; + +String16 jstringToString16(JNIEnv* env, jstring jstr) { + const jchar* str = env->GetStringCritical(jstr, 0); + String16 str16(str, env->GetStringLength(jstr)); + env->ReleaseStringCritical(jstr, str); + return str16; +} + +jstring string16ToJstring(JNIEnv* env, String16 string) { + const char16_t* str = string.string(); + size_t len = string.size(); + + return env->NewString(str, len); +} + +static jboolean com_android_pacprocessor_PacNative_createV8ParserNativeLocked(JNIEnv* env, + jobject) { + if (proxyResolver == NULL) { + logger = new ProxyErrorLogger(); + proxyResolver = new net::ProxyResolverV8(net::ProxyResolverJSBindings::CreateDefault(), + logger); + pacSet = false; + return JNI_FALSE; + } + return JNI_TRUE; +} + +static jboolean com_android_pacprocessor_PacNative_destroyV8ParserNativeLocked(JNIEnv* env, + jobject) { + if (proxyResolver != NULL) { + delete logger; + delete proxyResolver; + logger = NULL; + proxyResolver = NULL; + return JNI_FALSE; + } + return JNI_TRUE; +} + +static jboolean com_android_pacprocessor_PacNative_setProxyScriptNativeLocked(JNIEnv* env, jobject, + jstring script) { + String16 script16 = jstringToString16(env, script); + + if (proxyResolver == NULL) { + ALOGE("V8 Parser not started when setting PAC script"); + return JNI_TRUE; + } + + if (proxyResolver->SetPacScript(script16) != OK) { + ALOGE("Unable to set PAC script"); + return JNI_TRUE; + } + pacSet = true; + + return JNI_FALSE; +} + +static jstring com_android_pacprocessor_PacNative_makeProxyRequestNativeLocked(JNIEnv* env, jobject, + jstring url, jstring host) { + String16 url16 = jstringToString16(env, url); + String16 host16 = jstringToString16(env, host); + String16 ret; + + if (proxyResolver == NULL) { + ALOGE("V8 Parser not initialized when running PAC script"); + return NULL; + } + + if (!pacSet) { + ALOGW("Attempting to run PAC with no script set"); + return NULL; + } + + if (proxyResolver->GetProxyForURL(url16, host16, &ret) != OK) { + String8 ret8(ret); + ALOGE("Error Running PAC: %s", ret8.string()); + return NULL; + } + + jstring jret = string16ToJstring(env, ret); + + return jret; +} + +static JNINativeMethod gMethods[] = { + { "createV8ParserNativeLocked", "()Z", + (void*)com_android_pacprocessor_PacNative_createV8ParserNativeLocked}, + { "destroyV8ParserNativeLocked", "()Z", + (void*)com_android_pacprocessor_PacNative_destroyV8ParserNativeLocked}, + { "setProxyScriptNativeLocked", "(Ljava/lang/String;)Z", + (void*)com_android_pacprocessor_PacNative_setProxyScriptNativeLocked}, + { "makeProxyRequestNativeLocked", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", + (void*)com_android_pacprocessor_PacNative_makeProxyRequestNativeLocked}, +}; + +int register_com_android_pacprocessor_PacNative(JNIEnv* env) { + return jniRegisterNativeMethods(env, "com/android/pacprocessor/PacNative", + gMethods, NELEM(gMethods)); +} + +} /* namespace android */ diff --git a/packages/services/PacProcessor/jni/jni_init.cpp b/packages/services/PacProcessor/jni/jni_init.cpp new file mode 100644 index 000000000000..bda33fb33c07 --- /dev/null +++ b/packages/services/PacProcessor/jni/jni_init.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2013 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. + */ + +#define LOG_TAG "PacProcessor" + +#include +#include "jni.h" + +namespace android { + extern int register_com_android_pacprocessor_PacNative(JNIEnv *env); +} + +using namespace android; + +extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved) { + JNIEnv *env; + if (vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6) != JNI_OK) { + ALOGE("ERROR: GetEnv failed"); + return -1; + } + + register_com_android_pacprocessor_PacNative(env); + + return JNI_VERSION_1_6; +} diff --git a/packages/services/PacProcessor/main_pacserver.cpp b/packages/services/PacProcessor/main_pacserver.cpp deleted file mode 100644 index 19588b5074c2..000000000000 --- a/packages/services/PacProcessor/main_pacserver.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2010 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. - */ - -#define LOG_TAG "pacserver" -//#define LOG_NDEBUG 0 - -#include -#include -#include -#include -#include "ProxyService.h" -#include "proxy_resolver_v8.h" -#include - -using namespace android; - -int main(int argc, char** argv) -{ - sp proc(ProcessState::self()); - sp sm = defaultServiceManager(); - - printf("1\n"); - ALOGV("ServiceManager: %p", sm.get()); - ProxyService::instantiate(); - printf("1\n"); - - ProcessState::self()->startThreadPool(); - printf("1\n"); - IPCThreadState::self()->joinThreadPool(); -} diff --git a/packages/services/PacProcessor/res/values/strings.xml b/packages/services/PacProcessor/res/values/strings.xml new file mode 100644 index 000000000000..301a2b6cb1ee --- /dev/null +++ b/packages/services/PacProcessor/res/values/strings.xml @@ -0,0 +1,6 @@ + + + + PacProcessor + + diff --git a/packages/services/PacProcessor/src/com/android/pacprocessor/PacNative.java b/packages/services/PacProcessor/src/com/android/pacprocessor/PacNative.java new file mode 100644 index 000000000000..c67fe9ffa916 --- /dev/null +++ b/packages/services/PacProcessor/src/com/android/pacprocessor/PacNative.java @@ -0,0 +1,86 @@ +/** + * Copyright (c) 2013, 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 com.android.pacprocessor; + +import android.util.Log; + +/** + * @hide + */ +public class PacNative { + private static final String TAG = "PacProxy"; + + private String mCurrentPac; + + private boolean mIsActive; + + // Only make native calls from inside synchronized blocks. + private native boolean createV8ParserNativeLocked(); + private native boolean destroyV8ParserNativeLocked(); + + private native boolean setProxyScriptNativeLocked(String script); + + private native String makeProxyRequestNativeLocked(String url, String host); + + static { + System.loadLibrary("jni_pacprocessor"); + } + + PacNative() { + + } + + public synchronized boolean startPacSupport() { + if (createV8ParserNativeLocked()) { + Log.e(TAG, "Unable to Create v8 Proxy Parser."); + return true; + } + mIsActive = true; + return false; + } + + public synchronized boolean stopPacSupport() { + if (mIsActive) { + if (destroyV8ParserNativeLocked()) { + Log.e(TAG, "Unable to Destroy v8 Proxy Parser."); + return true; + } + mIsActive = false; + } + return false; + } + + public synchronized boolean setCurrentProxyScript(String script) { + if (setProxyScriptNativeLocked(script)) { + Log.e(TAG, "Unable to parse proxy script."); + return true; + } + return false; + } + + public synchronized String makeProxyRequest(String url, String host) { + String ret = makeProxyRequestNativeLocked(url, host); + if ((ret == null) || (ret.length() == 0)) { + Log.e(TAG, "v8 Proxy request failed."); + ret = null; + } + return ret; + } + + public synchronized boolean isActive() { + return mIsActive; + } +} diff --git a/packages/services/PacProcessor/src/com/android/pacprocessor/PacService.java b/packages/services/PacProcessor/src/com/android/pacprocessor/PacService.java new file mode 100644 index 000000000000..7e760251ac8a --- /dev/null +++ b/packages/services/PacProcessor/src/com/android/pacprocessor/PacService.java @@ -0,0 +1,101 @@ +/** + * Copyright (c) 2013, 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 com.android.pacprocessor; + +import android.app.Service; +import android.content.Intent; +import android.os.Binder; +import android.os.IBinder; +import android.os.Process; +import android.os.RemoteException; +import android.util.Log; + +import com.android.net.IProxyService; + +public class PacService extends Service { + private static final String TAG = "PacService"; + + private PacNative mPacNative; + private ProxyServiceStub mStub; + + @Override + public void onCreate() { + super.onCreate(); + if (mPacNative == null) { + mPacNative = new PacNative(); + mStub = new ProxyServiceStub(mPacNative); + } + } + + @Override + public void onDestroy() { + super.onDestroy(); + if (mPacNative != null) { + mPacNative.stopPacSupport(); + mPacNative = null; + mStub = null; + } + } + + @Override + public IBinder onBind(Intent intent) { + if (mPacNative == null) { + mPacNative = new PacNative(); + mStub = new ProxyServiceStub(mPacNative); + } + return mStub; + } + + private static class ProxyServiceStub extends IProxyService.Stub { + private final PacNative mPacNative; + + public ProxyServiceStub(PacNative pacNative) { + mPacNative = pacNative; + } + + @Override + public String resolvePacFile(String host, String url) throws RemoteException { + return mPacNative.makeProxyRequest(url, host); + } + + @Override + public void setPacFile(String script) throws RemoteException { + if (Binder.getCallingUid() != Process.SYSTEM_UID) { + Log.e(TAG, "Only system user is allowed to call setPacFile"); + throw new SecurityException(); + } + mPacNative.setCurrentProxyScript(script); + } + + @Override + public void startPacSystem() throws RemoteException { + if (Binder.getCallingUid() != Process.SYSTEM_UID) { + Log.e(TAG, "Only system user is allowed to call startPacSystem"); + throw new SecurityException(); + } + mPacNative.startPacSupport(); + } + + @Override + public void stopPacSystem() throws RemoteException { + if (Binder.getCallingUid() != Process.SYSTEM_UID) { + Log.e(TAG, "Only system user is allowed to call stopPacSystem"); + throw new SecurityException(); + } + mPacNative.stopPacSupport(); + } + } +} diff --git a/packages/services/Proxy/com/android/net/IProxyService.aidl b/packages/services/Proxy/com/android/net/IProxyService.aidl deleted file mode 100644 index 7e9ed799c7c3..000000000000 --- a/packages/services/Proxy/com/android/net/IProxyService.aidl +++ /dev/null @@ -1,16 +0,0 @@ -package com.android.net; - -/** @hide */ -interface IProxyService -{ - /** - * Keep up-to-date with - * frameworks/base/packages/services/PacProcessor/IProxyService.h - */ - String resolvePacFile(String host, String url); - - int setPacFile(String scriptContents); - - int startPacSystem(); - int stopPacSystem(); -} diff --git a/services/java/com/android/server/connectivity/PacManager.java b/services/java/com/android/server/connectivity/PacManager.java index defe9f075147..0b68ff5595eb 100644 --- a/services/java/com/android/server/connectivity/PacManager.java +++ b/services/java/com/android/server/connectivity/PacManager.java @@ -1,14 +1,31 @@ +/** + * Copyright (c) 2013, 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 com.android.server.connectivity; import android.app.AlarmManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; +import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import android.net.ConnectivityManager; +import android.content.ServiceConnection; import android.net.ProxyProperties; +import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; @@ -17,42 +34,26 @@ import android.provider.Settings; import android.text.TextUtils; import android.util.Log; +import com.android.internal.annotations.GuardedBy; import com.android.net.IProxyService; +import com.android.server.IoThread; +import libcore.io.Streams; -import org.apache.http.HttpEntity; -import org.apache.http.HttpException; -import org.apache.http.HttpHost; -import org.apache.http.HttpRequest; -import org.apache.http.HttpResponse; -import org.apache.http.client.ClientProtocolException; -import org.apache.http.client.HttpClient; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.conn.params.ConnRouteParams; -import org.apache.http.conn.routing.HttpRoute; -import org.apache.http.conn.routing.HttpRoutePlanner; -import org.apache.http.impl.client.DefaultHttpClient; -import org.apache.http.protocol.HttpContext; - -import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.net.InetAddress; -import java.net.ProxySelector; import java.net.URL; import java.net.URLConnection; /** * @hide */ -public class PacManager implements Runnable { - public static final int NO_ERROR = 0; - public static final int PERMISSION_DENIED = 1; - public static final String PROXY_SERVICE = "com.android.net.IProxyService"; +public class PacManager { + public static final String PROXY_PACKAGE = "com.android.pacprocessor"; + public static final String PROXY_SERVICE = "com.android.pacprocessor.PacService"; + public static final String PROXY_SERVICE_NAME = "com.android.net.IProxyService"; - private static final String TAG = "PACManager"; + private static final String TAG = "PacManager"; private static final String ACTION_PAC_REFRESH = "android.net.proxy.PAC_REFRESH"; @@ -64,31 +65,57 @@ public class PacManager implements Runnable { /** Keep these values up-to-date with ProxyService.java */ public static final String KEY_PROXY = "keyProxy"; private String mCurrentPac; - private volatile String mPacUrl; + @GuardedBy("mProxyLock") + private String mPacUrl; private AlarmManager mAlarmManager; + @GuardedBy("mProxyLock") private IProxyService mProxyService; private PendingIntent mPacRefreshIntent; + private ServiceConnection mConnection; private Context mContext; private int mCurrentDelay; + /** + * Used for locking when setting mProxyService and all references to mPacUrl or mCurrentPac. + */ + private final Object mProxyLock = new Object(); + + private Runnable mPacDownloader = new Runnable() { + @Override + public void run() { + String file; + synchronized (mProxyLock) { + if (mPacUrl == null) return; + try { + file = get(mPacUrl); + } catch (IOException ioe) { + file = null; + Log.w(TAG, "Failed to load PAC file: " + ioe); + } + } + if (file != null) { + synchronized (mProxyLock) { + if (!file.equals(mCurrentPac)) { + setCurrentProxyScript(file); + } + } + longSchedule(); + } else { + reschedule(); + } + } + }; + class PacRefreshIntentReceiver extends BroadcastReceiver { public void onReceive(Context context, Intent intent) { - new Thread(PacManager.this).start(); + IoThread.getHandler().post(mPacDownloader); } } public PacManager(Context context) { mContext = context; - mProxyService = IProxyService.Stub.asInterface( - ServiceManager.getService(PROXY_SERVICE)); - if (mProxyService == null) { - // Added because of b10267814 where mako is restarting. - Log.e(TAG, "PacManager: no proxy service"); - } else { - Log.d(TAG, "PacManager: mProxyService available"); - } mPacRefreshIntent = PendingIntent.getBroadcast( context, 0, new Intent(ACTION_PAC_REFRESH), 0); @@ -103,26 +130,28 @@ public class PacManager implements Runnable { return mAlarmManager; } - public void setCurrentProxyScriptUrl(ProxyProperties proxy) { - if (mProxyService == null) { - Log.e(TAG, "setCurrentProxyScriptUrl: no proxy service"); - return; - } + public synchronized void setCurrentProxyScriptUrl(ProxyProperties proxy) { if (!TextUtils.isEmpty(proxy.getPacFileUrl())) { - try { - mProxyService.startPacSystem(); + synchronized (mProxyLock) { mPacUrl = proxy.getPacFileUrl(); - mCurrentDelay = DELAY_1; - getAlarmManager().cancel(mPacRefreshIntent); - new Thread(this).start(); - } catch (RemoteException e) { - Log.e(TAG, "Unable to reach ProxyService - PAC will not be started", e); } + mCurrentDelay = DELAY_1; + getAlarmManager().cancel(mPacRefreshIntent); + bind(); } else { - try { - mProxyService.stopPacSystem(); - } catch (RemoteException e) { - e.printStackTrace(); + getAlarmManager().cancel(mPacRefreshIntent); + synchronized (mProxyLock) { + mPacUrl = null; + mCurrentPac = null; + if (mProxyService != null) { + try { + mProxyService.stopPacSystem(); + } catch (RemoteException e) { + Log.w(TAG, "Failed to stop PAC service", e); + } finally { + unbind(); + } + } } } } @@ -132,51 +161,10 @@ public class PacManager implements Runnable { * * @throws IOException */ - public static String get(String urlString) throws IOException { + private static String get(String urlString) throws IOException { URL url = new URL(urlString); URLConnection urlConnection = url.openConnection(java.net.Proxy.NO_PROXY); - BufferedReader in = new BufferedReader(new InputStreamReader( - urlConnection.getInputStream())); - String inputLine; - String resp = ""; - while ((inputLine = in.readLine()) != null) { - resp = resp + inputLine + "\n"; - } - in.close(); - return resp; - } - - private static String toString(InputStream content) throws IOException { - StringBuffer buffer = new StringBuffer(); - String line; - BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(content)); - - while ((line = bufferedReader.readLine()) != null) { - if (buffer.length() != 0) { - buffer.append('\n'); - } - buffer.append(line); - } - - return buffer.toString(); - } - - @Override - public void run() { - String file; - try { - file = get(mPacUrl); - } catch (IOException ioe) { - file = null; - } - if (file != null) { - if (!file.equals(mCurrentPac)) { - setCurrentProxyScript(file); - } - longSchedule(); - } else { - reschedule(); - } + return new String(Streams.readFully(urlConnection.getInputStream())); } private int getNextDelay(int currentDelay) { @@ -227,14 +215,60 @@ public class PacManager implements Runnable { return false; } try { - if (mProxyService.setPacFile(script) != NO_ERROR) { - Log.e(TAG, "Unable to parse proxy script."); - return false; - } + mProxyService.setPacFile(script); mCurrentPac = script; } catch (RemoteException e) { Log.e(TAG, "Unable to set PAC file", e); } return true; } + + private void bind() { + if (mContext == null) { + Log.e(TAG, "No context for binding"); + return; + } + Intent intent = new Intent(); + intent.setClassName(PROXY_PACKAGE, PROXY_SERVICE); + 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 " + PROXY_SERVICE_NAME + " " + + binder.getInterfaceDescriptor()); + } catch (RemoteException e1) { + Log.e(TAG, "Remote Exception", e1); + } + ServiceManager.addService(PROXY_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); + } + } + } + }; + Log.e(TAG, "Attempting to bind"); + mContext.bindService(intent, mConnection, + Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND | Context.BIND_NOT_VISIBLE); + } + + private void unbind() { + mContext.unbindService(mConnection); + mConnection = null; + } } -- 2.11.0