Merge "Change PacProcessor to Android Service" into klp-dev

This commit is contained in:
Jason Monk
2013-08-20 23:35:26 +00:00
committed by Android (Google) Code Review
21 changed files with 634 additions and 468 deletions

View File

@@ -262,7 +262,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)

View File

@@ -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
# ************************************************

View File

@@ -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,18 +40,24 @@ 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<Proxy> 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<Proxy> 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);
}

View File

@@ -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);
}

View File

@@ -218,6 +218,7 @@
<protected-broadcast android:name="android.location.GPS_ENABLED_CHANGE" />
<protected-broadcast android:name="android.location.PROVIDERS_CHANGED" />
<protected-broadcast android:name="android.location.GPS_FIX_CHANGE" />
<protected-broadcast android:name="android.net.proxy.PAC_REFRESH" />
<!-- ====================================== -->
<!-- Permissions for things that cost money -->

View File

@@ -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))

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.pacprocessor">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:label="@string/app_name">
<service android:name=".PacService"
android:exported="true">
</service>
</application>
</manifest>

View File

@@ -1,97 +0,0 @@
#define LOG_TAG "ProxyTesting"
#include <stdint.h>
#include <sys/types.h>
#include <binder/Parcel.h>
#include <binder/IPCThreadState.h>
#include <utils/Errors.h>
#include "IProxyService.h"
#include <utils/Log.h>
#include <private/android_filesystem_config.h>
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;
}

View File

@@ -1,59 +0,0 @@
#ifndef IPROXY_SERVICE_H
#define IPROXY_SERVICE_H
#include <binder/IInterface.h>
#include <binder/IBinder.h>
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<IProxyService> {
public:
BpProxyService(const sp<IBinder>& impl) : BpInterface<IProxyService>(impl) {}
virtual String16 resolveProxies(String16 host, String16 url);
virtual void setPacFile(String16& scriptContents);
virtual void startPacSystem();
virtual void stopPacSystem();
};
class BnProxyService : public BnInterface<IProxyService> {
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

View File

@@ -1,96 +0,0 @@
#define LOG_TAG "ProxyService"
#include <utils/Log.h>
#include <errno.h>
#include <utils/threads.h>
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
#include <sys/stat.h>
#include <proxy_resolver_v8.h>
#include <sstream>
#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;
}
}

View File

@@ -1,33 +0,0 @@
#ifndef PROXY_SERVICE_H
#define PROXY_SERVICE_H
#include <binder/IInterface.h>
#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

View File

@@ -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();
}

View File

@@ -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)

View File

@@ -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 <utils/Log.h>
#include <utils/Mutex.h>
#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 */

View File

@@ -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 <utils/Log.h>
#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<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
ALOGE("ERROR: GetEnv failed");
return -1;
}
register_com_android_pacprocessor_PacNative(env);
return JNI_VERSION_1_6;
}

View File

@@ -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 <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <utils/Log.h>
#include "ProxyService.h"
#include "proxy_resolver_v8.h"
#include <stdio.h>
using namespace android;
int main(int argc, char** argv)
{
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm = defaultServiceManager();
printf("1\n");
ALOGV("ServiceManager: %p", sm.get());
ProxyService::instantiate();
printf("1\n");
ProcessState::self()->startThreadPool();
printf("1\n");
IPCThreadState::self()->joinThreadPool();
}

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">PacProcessor</string>
</resources>

View File

@@ -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;
}
}

View File

@@ -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();
}
}
}

View File

@@ -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();
}

View File

@@ -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;
}
}