diff options
-rw-r--r-- | Android.mk | 1 | ||||
-rw-r--r-- | core/java/android/os/INetworkManagementService.aidl | 105 | ||||
-rw-r--r-- | include/media/IMediaDeathNotifier.h | 61 | ||||
-rw-r--r-- | include/media/mediaplayer.h | 28 | ||||
-rw-r--r-- | include/media/mediarecorder.h | 5 | ||||
-rw-r--r-- | media/libmedia/Android.mk | 3 | ||||
-rw-r--r-- | media/libmedia/IMediaDeathNotifier.cpp | 111 | ||||
-rw-r--r-- | media/libmedia/mediaplayer.cpp | 90 | ||||
-rw-r--r-- | media/libmedia/mediarecorder.cpp | 20 | ||||
-rw-r--r-- | media/tests/omxjpegdecoder/Android.mk | 3 | ||||
-rw-r--r-- | services/java/com/android/server/LocationManagerService.java | 4 | ||||
-rw-r--r-- | services/java/com/android/server/NetworkManagementService.java | 303 |
12 files changed, 610 insertions, 124 deletions
@@ -111,6 +111,7 @@ LOCAL_SRC_FILES += \ core/java/android/os/ICheckinService.aidl \ core/java/android/os/IMessenger.aidl \ core/java/android/os/IMountService.aidl \ + core/java/android/os/INetworkManagementService.aidl \ core/java/android/os/INetStatService.aidl \ core/java/android/os/IParentalControlCallback.aidl \ core/java/android/os/IPermissionController.aidl \ diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl new file mode 100644 index 0000000..bd6cabb --- /dev/null +++ b/core/java/android/os/INetworkManagementService.aidl @@ -0,0 +1,105 @@ +/* //device/java/android/android/os/INetworkManagementService.aidl +** +** Copyright 2007, 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.os; + +/** + * @hide + */ +interface INetworkManagementService +{ + /** + ** GENERAL + **/ + + /** + * Returns a list of currently known network interfaces + */ + String[] listInterfaces(); + + /** + * Shuts down the service + */ + void shutdown(); + + /** + ** TETHERING RELATED + **/ + + + /** + * Returns true if IP forwarding is enabled + */ + boolean getIpForwardingEnabled(); + + /** + * Enables/Disables IP Forwarding + */ + void setIpForwardingEnabled(boolean enabled); + + /** + * Start tethering services with the specified dhcp server range + */ + void startTethering(String dhcpRangeStart, String dhcpRangeEnd); + + /** + * Stop currently running tethering services + */ + void stopTethering(); + + /** + * Returns true if tethering services are started + */ + boolean isTetheringStarted(); + + /** + * Tethers the specified interface + */ + void tetherInterface(String iface); + + /** + * Untethers the specified interface + */ + void untetherInterface(String iface); + + /** + * Returns a list of currently tethered interfaces + */ + String[] listTetheredInterfaces(); + + /** + * Sets the list of DNS forwarders (in order of priority) + */ + void setDnsForwarders(in String[] dns); + + /** + * Returns the list of DNS fowarders (in order of priority) + */ + String[] getDnsForwarders(); + + /** + * Enables Network Address Translation between two interfaces. + * The address and netmask of the external interface is used for + * the NAT'ed network. + */ + void enableNat(String internalInterface, String externalInterface); + + /** + * Disables Network Address Translation between two interfaces. + */ + void disableNat(String internalInterface, String externalInterface); +} diff --git a/include/media/IMediaDeathNotifier.h b/include/media/IMediaDeathNotifier.h new file mode 100644 index 0000000..bb3d0d8 --- /dev/null +++ b/include/media/IMediaDeathNotifier.h @@ -0,0 +1,61 @@ +/* + * 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. + */ + +#ifndef ANDROID_IMEDIADEATHNOTIFIER_H +#define ANDROID_IMEDIADEATHNOTIFIER_H + +#include <utils/threads.h> +#include <media/IMediaPlayerService.h> +#include <utils/SortedVector.h> + +namespace android { + +class IMediaDeathNotifier: virtual public RefBase +{ +public: + IMediaDeathNotifier() { addObitRecipient(this); } + virtual ~IMediaDeathNotifier() { removeObitRecipient(this); } + + virtual void died() = 0; + static const sp<IMediaPlayerService>& getMediaPlayerService(); + +private: + IMediaDeathNotifier &operator=(const IMediaDeathNotifier &); + IMediaDeathNotifier(const IMediaDeathNotifier &); + + static void addObitRecipient(const wp<IMediaDeathNotifier>& recipient); + static void removeObitRecipient(const wp<IMediaDeathNotifier>& recipient); + + class DeathNotifier: public IBinder::DeathRecipient + { + public: + DeathNotifier() {} + virtual ~DeathNotifier(); + + virtual void binderDied(const wp<IBinder>& who); + }; + + friend class DeathNotifier; + + static Mutex sServiceLock; + static sp<IMediaPlayerService> sMediaPlayerService; + static sp<DeathNotifier> sDeathNotifier; + static SortedVector< wp<IMediaDeathNotifier> > sObitRecipients; +}; + +}; // namespace android + +#endif // ANDROID_IMEDIADEATHNOTIFIER_H diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h index 7132b18..87d23f6 100644 --- a/include/media/mediaplayer.h +++ b/include/media/mediaplayer.h @@ -21,8 +21,7 @@ #include <ui/Surface.h> #include <media/IMediaPlayerClient.h> #include <media/IMediaPlayer.h> -#include <media/IMediaPlayerService.h> -#include <utils/SortedVector.h> +#include <media/IMediaDeathNotifier.h> namespace android { @@ -123,12 +122,13 @@ public: virtual void notify(int msg, int ext1, int ext2) = 0; }; -class MediaPlayer : public BnMediaPlayerClient +class MediaPlayer : public BnMediaPlayerClient, + public virtual IMediaDeathNotifier { public: MediaPlayer(); ~MediaPlayer(); - void onFirstRef(); + void died(); void disconnect(); status_t setDataSource(const char *url); status_t setDataSource(int fd, int64_t offset, int64_t length); @@ -164,19 +164,6 @@ private: status_t getDuration_l(int *msec); status_t setDataSource(const sp<IMediaPlayer>& player); - static const sp<IMediaPlayerService>& getMediaPlayerService(); - static void addObitRecipient(const wp<MediaPlayer>& recipient); - static void removeObitRecipient(const wp<MediaPlayer>& recipient); - - class DeathNotifier: public IBinder::DeathRecipient - { - public: - DeathNotifier() {} - virtual ~DeathNotifier(); - - virtual void binderDied(const wp<IBinder>& who); - }; - sp<IMediaPlayer> mPlayer; thread_id_t mLockThreadId; Mutex mLock; @@ -196,13 +183,6 @@ private: float mRightVolume; int mVideoWidth; int mVideoHeight; - - friend class DeathNotifier; - - static Mutex sServiceLock; - static sp<IMediaPlayerService> sMediaPlayerService; - static sp<DeathNotifier> sDeathNotifier; - static SortedVector< wp<MediaPlayer> > sObitRecipients; }; }; // namespace android diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h index 8c7392b..9ea6c7b 100644 --- a/include/media/mediarecorder.h +++ b/include/media/mediarecorder.h @@ -23,6 +23,7 @@ #include <utils/List.h> #include <utils/Errors.h> #include <media/IMediaPlayerClient.h> +#include <media/IMediaDeathNotifier.h> namespace android { @@ -145,12 +146,14 @@ public: virtual void notify(int msg, int ext1, int ext2) = 0; }; -class MediaRecorder : public BnMediaPlayerClient +class MediaRecorder : public BnMediaPlayerClient, + public virtual IMediaDeathNotifier { public: MediaRecorder(); ~MediaRecorder(); + void died(); status_t initCheck(); status_t setCamera(const sp<ICamera>& camera); status_t setPreviewSurface(const sp<Surface>& surface); diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk index fc234ee..4ae4ec9b 100644 --- a/media/libmedia/Android.mk +++ b/media/libmedia/Android.mk @@ -24,7 +24,8 @@ LOCAL_SRC_FILES:= \ IAudioPolicyService.cpp \ MediaScanner.cpp \ MediaScannerClient.cpp \ - autodetect.cpp + autodetect.cpp \ + IMediaDeathNotifier.cpp LOCAL_SHARED_LIBRARIES := \ libui libcutils libutils libbinder libsonivox libicuuc diff --git a/media/libmedia/IMediaDeathNotifier.cpp b/media/libmedia/IMediaDeathNotifier.cpp new file mode 100644 index 0000000..39ac076 --- /dev/null +++ b/media/libmedia/IMediaDeathNotifier.cpp @@ -0,0 +1,111 @@ +/* +** Copyright 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_NDEBUG 0 +#define LOG_TAG "IMediaDeathNotifier" +#include <utils/Log.h> + +#include <binder/IServiceManager.h> +#include <binder/IPCThreadState.h> +#include <media/IMediaDeathNotifier.h> + +namespace android { + +// client singleton for binder interface to services +Mutex IMediaDeathNotifier::sServiceLock; +sp<IMediaPlayerService> IMediaDeathNotifier::sMediaPlayerService; +sp<IMediaDeathNotifier::DeathNotifier> IMediaDeathNotifier::sDeathNotifier; +SortedVector< wp<IMediaDeathNotifier> > IMediaDeathNotifier::sObitRecipients; + +// establish binder interface to MediaPlayerService +/*static*/const sp<IMediaPlayerService>& +IMediaDeathNotifier::getMediaPlayerService() +{ + LOGV("getMediaPlayerService"); + Mutex::Autolock _l(sServiceLock); + if (sMediaPlayerService.get() == 0) { + sp<IServiceManager> sm = defaultServiceManager(); + sp<IBinder> binder; + do { + binder = sm->getService(String16("media.player")); + if (binder != 0) { + break; + } + LOGW("Media player service not published, waiting..."); + usleep(500000); // 0.5 s + } while(true); + + if (sDeathNotifier == NULL) { + sDeathNotifier = new DeathNotifier(); + } + binder->linkToDeath(sDeathNotifier); + sMediaPlayerService = interface_cast<IMediaPlayerService>(binder); + } + LOGE_IF(sMediaPlayerService == 0, "no media player service!?"); + return sMediaPlayerService; +} + +/*static*/ void +IMediaDeathNotifier::addObitRecipient(const wp<IMediaDeathNotifier>& recipient) +{ + LOGV("addObitRecipient"); + Mutex::Autolock _l(sServiceLock); + sObitRecipients.add(recipient); +} + +/*static*/ void +IMediaDeathNotifier::removeObitRecipient(const wp<IMediaDeathNotifier>& recipient) +{ + LOGV("removeObitRecipient"); + Mutex::Autolock _l(sServiceLock); + sObitRecipients.remove(recipient); +} + +void +IMediaDeathNotifier::DeathNotifier::binderDied(const wp<IBinder>& who) { + LOGW("media server died"); + + // Need to do this with the lock held + SortedVector< wp<IMediaDeathNotifier> > list; + { + Mutex::Autolock _l(sServiceLock); + sMediaPlayerService.clear(); + list = sObitRecipients; + } + + // Notify application when media server dies. + // Don't hold the static lock during callback in case app + // makes a call that needs the lock. + size_t count = list.size(); + for (size_t iter = 0; iter < count; ++iter) { + sp<IMediaDeathNotifier> notifier = list[iter].promote(); + if (notifier != 0) { + notifier->died(); + } + } +} + +IMediaDeathNotifier::DeathNotifier::~DeathNotifier() +{ + LOGV("DeathNotifier::~DeathNotifier"); + Mutex::Autolock _l(sServiceLock); + sObitRecipients.clear(); + if (sMediaPlayerService != 0) { + sMediaPlayerService->asBinder()->unlinkToDeath(this); + } +} + +}; // namespace android diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp index 040366b..c0664f3 100644 --- a/media/libmedia/mediaplayer.cpp +++ b/media/libmedia/mediaplayer.cpp @@ -34,48 +34,6 @@ namespace android { -// client singleton for binder interface to service -Mutex MediaPlayer::sServiceLock; -sp<IMediaPlayerService> MediaPlayer::sMediaPlayerService; -sp<MediaPlayer::DeathNotifier> MediaPlayer::sDeathNotifier; -SortedVector< wp<MediaPlayer> > MediaPlayer::sObitRecipients; - -// establish binder interface to service -const sp<IMediaPlayerService>& MediaPlayer::getMediaPlayerService() -{ - Mutex::Autolock _l(sServiceLock); - if (sMediaPlayerService.get() == 0) { - sp<IServiceManager> sm = defaultServiceManager(); - sp<IBinder> binder; - do { - binder = sm->getService(String16("media.player")); - if (binder != 0) - break; - LOGW("MediaPlayerService not published, waiting..."); - usleep(500000); // 0.5 s - } while(true); - if (sDeathNotifier == NULL) { - sDeathNotifier = new DeathNotifier(); - } - binder->linkToDeath(sDeathNotifier); - sMediaPlayerService = interface_cast<IMediaPlayerService>(binder); - } - LOGE_IF(sMediaPlayerService==0, "no MediaPlayerService!?"); - return sMediaPlayerService; -} - -void MediaPlayer::addObitRecipient(const wp<MediaPlayer>& recipient) -{ - Mutex::Autolock _l(sServiceLock); - sObitRecipients.add(recipient); -} - -void MediaPlayer::removeObitRecipient(const wp<MediaPlayer>& recipient) -{ - Mutex::Autolock _l(sServiceLock); - sObitRecipients.remove(recipient); -} - MediaPlayer::MediaPlayer() { LOGV("constructor"); @@ -94,15 +52,9 @@ MediaPlayer::MediaPlayer() mLockThreadId = 0; } -void MediaPlayer::onFirstRef() -{ - addObitRecipient(this); -} - MediaPlayer::~MediaPlayer() { LOGV("destructor"); - removeObitRecipient(this); disconnect(); IPCThreadState::self()->flushCommands(); } @@ -630,45 +582,13 @@ void MediaPlayer::notify(int msg, int ext1, int ext2) } } -void MediaPlayer::DeathNotifier::binderDied(const wp<IBinder>& who) { - LOGW("MediaPlayer server died!"); - - // Need to do this with the lock held - SortedVector< wp<MediaPlayer> > list; - { - Mutex::Autolock _l(MediaPlayer::sServiceLock); - MediaPlayer::sMediaPlayerService.clear(); - list = sObitRecipients; - } - - // Notify application when media server dies. - // Don't hold the static lock during callback in case app - // makes a call that needs the lock. - size_t count = list.size(); - for (size_t iter = 0; iter < count; ++iter) { - sp<MediaPlayer> player = list[iter].promote(); - if ((player != 0) && (player->mPlayer != 0)) { - player->notify(MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED, 0); - } - } -} - -MediaPlayer::DeathNotifier::~DeathNotifier() -{ - Mutex::Autolock _l(sServiceLock); - sObitRecipients.clear(); - if (sMediaPlayerService != 0) { - sMediaPlayerService->asBinder()->unlinkToDeath(this); - } -} - /*static*/ sp<IMemory> MediaPlayer::decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) { LOGV("decode(%s)", url); sp<IMemory> p; const sp<IMediaPlayerService>& service = getMediaPlayerService(); if (service != 0) { - p = sMediaPlayerService->decode(url, pSampleRate, pNumChannels, pFormat); + p = service->decode(url, pSampleRate, pNumChannels, pFormat); } else { LOGE("Unable to locate media service"); } @@ -676,13 +596,19 @@ MediaPlayer::DeathNotifier::~DeathNotifier() } +void MediaPlayer::died() +{ + LOGV("died"); + notify(MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED, 0); +} + /*static*/ sp<IMemory> MediaPlayer::decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) { LOGV("decode(%d, %lld, %lld)", fd, offset, length); sp<IMemory> p; const sp<IMediaPlayerService>& service = getMediaPlayerService(); if (service != 0) { - p = sMediaPlayerService->decode(fd, offset, length, pSampleRate, pNumChannels, pFormat); + p = service->decode(fd, offset, length, pSampleRate, pNumChannels, pFormat); } else { LOGE("Unable to locate media service"); } diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp index 6b63931..7b5dabb 100644 --- a/media/libmedia/mediarecorder.cpp +++ b/media/libmedia/mediarecorder.cpp @@ -24,6 +24,7 @@ #include <utils/String8.h> #include <media/IMediaPlayerService.h> #include <media/IMediaRecorder.h> +#include <media/mediaplayer.h> // for MEDIA_ERROR_SERVER_DIED namespace android { @@ -576,19 +577,8 @@ status_t MediaRecorder::release() MediaRecorder::MediaRecorder() { LOGV("constructor"); - sp<IServiceManager> sm = defaultServiceManager(); - sp<IBinder> binder; - do { - binder = sm->getService(String16("media.player")); - if (binder != NULL) { - break; - } - LOGW("MediaPlayerService not published, waiting..."); - usleep(500000); // 0.5 s - } while(true); - - sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder); + const sp<IMediaPlayerService>& service(getMediaPlayerService()); if (service != NULL) { mMediaRecorder = service->createMediaRecorder(getpid()); } @@ -637,5 +627,11 @@ void MediaRecorder::notify(int msg, int ext1, int ext2) } } +void MediaRecorder::died() +{ + LOGV("died"); + notify(MEDIA_RECORDER_EVENT_ERROR, MEDIA_ERROR_SERVER_DIED, 0); +} + }; // namespace android diff --git a/media/tests/omxjpegdecoder/Android.mk b/media/tests/omxjpegdecoder/Android.mk index f679f19..b7c18bc 100644 --- a/media/tests/omxjpegdecoder/Android.mk +++ b/media/tests/omxjpegdecoder/Android.mk @@ -33,7 +33,8 @@ LOCAL_SHARED_LIBRARIES := \ libskia \ libstagefright \ libbinder \ - libutils + libutils \ + libjpeg LOCAL_C_INCLUDES := \ $(JNI_H_INCLUDE) \ diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java index 406897d..1c82c94 100644 --- a/services/java/com/android/server/LocationManagerService.java +++ b/services/java/com/android/server/LocationManagerService.java @@ -1203,12 +1203,10 @@ public class LocationManagerService extends ILocationManager.Stub implements Run // Remove expired alerts if (intentsToRemove != null) { for (PendingIntent i : intentsToRemove) { - mProximityAlerts.remove(i); - ProximityAlert alert = mProximityAlerts.get(i); + ProximityAlert alert = mProximityAlerts.remove(i); mProximitiesEntered.remove(alert); } } - } // Note: this is called with the lock held. diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java new file mode 100644 index 0000000..97fa0cc --- /dev/null +++ b/services/java/com/android/server/NetworkManagementService.java @@ -0,0 +1,303 @@ +/* + * Copyright (C) 2007 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; + +import android.app.PendingIntent; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.res.Resources; +import android.content.pm.PackageManager; +import android.net.Uri; +import android.os.INetworkManagementService; +import android.os.Handler; +import android.text.TextUtils; +import android.util.Log; +import java.util.ArrayList; + +import android.provider.Settings; +import android.content.ContentResolver; +import android.database.ContentObserver; + +import java.io.File; +import java.io.FileReader; +import java.lang.IllegalStateException; + +import java.net.InetAddress; +import java.net.UnknownHostException; + +/** + * @hide + */ +class NetworkManagementService extends INetworkManagementService.Stub { + + private static final String TAG = "NetworkManagmentService"; + + class NetdResponseCode { + public static final int InterfaceListResult = 110; + public static final int TetherInterfaceListResult = 111; + public static final int TetherDnsFwdTgtListResult = 112; + + public static final int TetherStatusResult = 210; + public static final int IpFwdStatusResult = 211; + } + + /** + * Binder context for this service + */ + private Context mContext; + + /** + * connector object for communicating with netd + */ + private NativeDaemonConnector mConnector; + + /** + * Constructs a new NetworkManagementService instance + * + * @param context Binder context for this service + */ + private NetworkManagementService(Context context) { + mContext = context; + + mConnector = new NativeDaemonConnector( + new NetdCallbackReceiver(), "netd", 10, "NetdConnector"); + Thread thread = new Thread(mConnector, NativeDaemonConnector.class.getName()); + thread.start(); + } + + // + // Netd Callback handling + // + + class NetdCallbackReceiver implements INativeDaemonConnectorCallbacks { + public void onDaemonConnected() { + new Thread() { + public void run() { + // XXX: Run some tests + } + }.start(); + } + public boolean onEvent(int code, String raw, String[] cooked) { + return false; + } + } + + // + // INetworkManagementService members + // + + public String[] listInterfaces() throws IllegalStateException { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); + + ArrayList<String> rsp = mConnector.doCommand("list_interfaces"); + + String[] rdata = new String[rsp.size()]; + int idx = 0; + + for (String line : rsp) { + String []tok = line.split(" "); + int code = Integer.parseInt(tok[0]); + if (code == NetdResponseCode.InterfaceListResult) { + if (tok.length !=2) { + throw new IllegalStateException( + String.format("Malformatted list entry '%s'", line)); + } + rdata[idx++] = tok[1]; + } else if (code == NativeDaemonConnector.ResponseCode.CommandOkay) { + return rdata; + } else { + throw new IllegalStateException(String.format("Unexpected response code %d", code)); + } + } + throw new IllegalStateException("Got an empty response"); + } + + public void shutdown() { + if (mContext.checkCallingOrSelfPermission( + android.Manifest.permission.SHUTDOWN) + != PackageManager.PERMISSION_GRANTED) { + throw new SecurityException("Requires SHUTDOWN permission"); + } + + Log.d(TAG, "Shutting down"); + } + + public boolean getIpForwardingEnabled() throws IllegalStateException{ + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); + + ArrayList<String> rsp = mConnector.doCommand("ipfwd status"); + + for (String line : rsp) { + String []tok = line.split(" "); + int code = Integer.parseInt(tok[0]); + if (code == NetdResponseCode.IpFwdStatusResult) { + // 211 Forwarding <enabled/disabled> + if (tok.length !=2) { + throw new IllegalStateException( + String.format("Malformatted list entry '%s'", line)); + } + if (tok[2].equals("enabled")) + return true; + return false; + } else { + throw new IllegalStateException(String.format("Unexpected response code %d", code)); + } + } + throw new IllegalStateException("Got an empty response"); + } + + public void setIpForwardingEnabled(boolean enable) throws IllegalStateException { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); + mConnector.doCommand(String.format("ipfwd %sable", (enable ? "en" : "dis"))); + } + + public void startTethering(String dhcpRangeStart, String dhcpRangeEnd) + throws IllegalStateException { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); + mConnector.doCommand(String.format("tether start %s %s", dhcpRangeStart, dhcpRangeEnd)); + } + + public void stopTethering() throws IllegalStateException { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); + mConnector.doCommand("tether stop"); + } + + public boolean isTetheringStarted() throws IllegalStateException { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); + + ArrayList<String> rsp = mConnector.doCommand("tether status"); + + for (String line : rsp) { + String []tok = line.split(" "); + int code = Integer.parseInt(tok[0]); + if (code == NetdResponseCode.TetherStatusResult) { + // XXX: Tethering services <started/stopped> <TBD>... + if (tok[2].equals("started")) + return true; + return false; + } else { + throw new IllegalStateException(String.format("Unexpected response code %d", code)); + } + } + throw new IllegalStateException("Got an empty response"); + } + + public void tetherInterface(String iface) throws IllegalStateException { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); + mConnector.doCommand("tether interface add " + iface); + } + + public void untetherInterface(String iface) { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); + mConnector.doCommand("tether interface remove " + iface); + } + + public String[] listTetheredInterfaces() throws IllegalStateException { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); + + ArrayList<String> rsp = mConnector.doCommand("tether interface list"); + + String[] rdata = new String[rsp.size()]; + int idx = 0; + + for (String line : rsp) { + String []tok = line.split(" "); + int code = Integer.parseInt(tok[0]); + if (code == NetdResponseCode.TetherInterfaceListResult) { + if (tok.length !=2) { + throw new IllegalStateException( + String.format("Malformatted list entry '%s'", line)); + } + rdata[idx++] = tok[1]; + } else if (code == NativeDaemonConnector.ResponseCode.CommandOkay) { + return rdata; + } else { + throw new IllegalStateException(String.format("Unexpected response code %d", code)); + } + } + throw new IllegalStateException("Got an empty response"); + } + + public void setDnsForwarders(String[] dns) throws IllegalStateException { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); + try { + String cmd = "tether dns set "; + for (String s : dns) { + cmd += InetAddress.getByName(s).toString() + " "; + } + mConnector.doCommand(cmd); + } catch (UnknownHostException e) { + throw new IllegalStateException("Error resolving dns name", e); + } + } + + public String[] getDnsForwarders() throws IllegalStateException { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); + + ArrayList<String> rsp = mConnector.doCommand("tether dns list"); + + String[] rdata = new String[rsp.size()]; + int idx = 0; + + for (String line : rsp) { + String []tok = line.split(" "); + int code = Integer.parseInt(tok[0]); + if (code == NetdResponseCode.TetherDnsFwdTgtListResult) { + if (tok.length !=2) { + throw new IllegalStateException( + String.format("Malformatted list entry '%s'", line)); + } + rdata[idx++] = tok[1]; + } else if (code == NativeDaemonConnector.ResponseCode.CommandOkay) { + return rdata; + } else { + throw new IllegalStateException(String.format("Unexpected response code %d", code)); + } + } + throw new IllegalStateException("Got an empty response"); + } + + public void enableNat(String internalInterface, String externalInterface) + throws IllegalStateException { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); + mConnector.doCommand( + String.format("nat enable %s %s", internalInterface, externalInterface)); + } + + public void disableNat(String internalInterface, String externalInterface) + throws IllegalStateException { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); + mConnector.doCommand( + String.format("nat disable %s %s", internalInterface, externalInterface)); + } +} + |