diff options
-rw-r--r-- | core/java/android/os/StrictMode.java | 33 | ||||
-rw-r--r-- | media/libstagefright/rtsp/MyHandler.h | 153 | ||||
-rwxr-xr-x | services/java/com/android/server/location/GpsLocationProvider.java | 8 | ||||
-rwxr-xr-x | services/jni/com_android_server_location_GpsLocationProvider.cpp | 18 | ||||
-rw-r--r-- | services/surfaceflinger/MessageQueue.cpp | 18 |
5 files changed, 215 insertions, 15 deletions
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java index 9494a06a7f79..c185007f103e 100644 --- a/core/java/android/os/StrictMode.java +++ b/core/java/android/os/StrictMode.java @@ -104,6 +104,10 @@ public final class StrictMode { // Only show an annoying dialog at most every 30 seconds private static final long MIN_DIALOG_INTERVAL_MS = 30000; + // How many offending stacks to keep track of (and time) per loop + // of the Looper. + private static final int MAX_OFFENSES_PER_LOOP = 10; + // Thread-policy: /** @@ -680,6 +684,17 @@ public final class StrictMode { } } + private static final ThreadLocal<ArrayList<ViolationInfo>> violationsBeingTimed = + new ThreadLocal<ArrayList<ViolationInfo>>() { + @Override protected ArrayList<ViolationInfo> initialValue() { + return new ArrayList<ViolationInfo>(); + } + }; + + private static boolean tooManyViolationsThisLoop() { + return violationsBeingTimed.get().size() >= MAX_OFFENSES_PER_LOOP; + } + private static class AndroidBlockGuardPolicy implements BlockGuard.Policy { private int mPolicyMask; @@ -707,6 +722,9 @@ public final class StrictMode { if ((mPolicyMask & DETECT_DISK_WRITE) == 0) { return; } + if (tooManyViolationsThisLoop()) { + return; + } BlockGuard.BlockGuardPolicyException e = new StrictModeDiskWriteViolation(mPolicyMask); e.fillInStackTrace(); startHandlingViolationException(e); @@ -717,6 +735,9 @@ public final class StrictMode { if ((mPolicyMask & DETECT_DISK_READ) == 0) { return; } + if (tooManyViolationsThisLoop()) { + return; + } BlockGuard.BlockGuardPolicyException e = new StrictModeDiskReadViolation(mPolicyMask); e.fillInStackTrace(); startHandlingViolationException(e); @@ -727,6 +748,9 @@ public final class StrictMode { if ((mPolicyMask & DETECT_NETWORK) == 0) { return; } + if (tooManyViolationsThisLoop()) { + return; + } BlockGuard.BlockGuardPolicyException e = new StrictModeNetworkViolation(mPolicyMask); e.fillInStackTrace(); startHandlingViolationException(e); @@ -747,13 +771,6 @@ public final class StrictMode { handleViolationWithTimingAttempt(info); } - private static final ThreadLocal<ArrayList<ViolationInfo>> violationsBeingTimed = - new ThreadLocal<ArrayList<ViolationInfo>>() { - @Override protected ArrayList<ViolationInfo> initialValue() { - return new ArrayList<ViolationInfo>(); - } - }; - // Attempts to fill in the provided ViolationInfo's // durationMillis field if this thread has a Looper we can use // to measure with. We measure from the time of violation @@ -780,7 +797,7 @@ public final class StrictMode { MessageQueue queue = Looper.myQueue(); final ArrayList<ViolationInfo> records = violationsBeingTimed.get(); - if (records.size() >= 10) { + if (records.size() >= MAX_OFFENSES_PER_LOOP) { // Not worth measuring. Too many offenses in one loop. return; } diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h index 05dd61b9ac86..0f4c1f37f43c 100644 --- a/media/libstagefright/rtsp/MyHandler.h +++ b/media/libstagefright/rtsp/MyHandler.h @@ -28,6 +28,7 @@ #include "ASessionDescription.h" #include <ctype.h> +#include <cutils/properties.h> #include <media/stagefright/foundation/ABuffer.h> #include <media/stagefright/foundation/ADebug.h> @@ -35,6 +36,9 @@ #include <media/stagefright/foundation/AMessage.h> #include <media/stagefright/MediaErrors.h> +#include <arpa/inet.h> +#include <sys/socket.h> + // If no access units are received within 3 secs, assume that the rtp // stream has ended and signal end of stream. static int64_t kAccessUnitTimeoutUs = 3000000ll; @@ -45,6 +49,19 @@ static int64_t kStartupTimeoutUs = 10000000ll; namespace android { +static void MakeUserAgentString(AString *s) { + s->setTo("stagefright/1.1 (Linux;Android "); + +#if (PROPERTY_VALUE_MAX < 8) +#error "PROPERTY_VALUE_MAX must be at least 8" +#endif + + char value[PROPERTY_VALUE_MAX]; + property_get("ro.build.version.release", value, "Unknown"); + s->append(value); + s->append(")"); +} + static bool GetAttribute(const char *s, const char *key, AString *value) { value->clear(); @@ -137,6 +154,131 @@ struct MyHandler : public AHandler { return maxTimeUs; } + static void addRR(const sp<ABuffer> &buf) { + uint8_t *ptr = buf->data() + buf->size(); + ptr[0] = 0x80 | 0; + ptr[1] = 201; // RR + ptr[2] = 0; + ptr[3] = 1; + ptr[4] = 0xde; // SSRC + ptr[5] = 0xad; + ptr[6] = 0xbe; + ptr[7] = 0xef; + + buf->setRange(0, buf->size() + 8); + } + + static void addSDES(int s, const sp<ABuffer> &buffer) { + struct sockaddr_in addr; + socklen_t addrSize = sizeof(addr); + CHECK_EQ(0, getsockname(s, (sockaddr *)&addr, &addrSize)); + + uint8_t *data = buffer->data() + buffer->size(); + data[0] = 0x80 | 1; + data[1] = 202; // SDES + data[4] = 0xde; // SSRC + data[5] = 0xad; + data[6] = 0xbe; + data[7] = 0xef; + + size_t offset = 8; + + data[offset++] = 1; // CNAME + + AString cname = "stagefright@"; + cname.append(inet_ntoa(addr.sin_addr)); + data[offset++] = cname.size(); + + memcpy(&data[offset], cname.c_str(), cname.size()); + offset += cname.size(); + + data[offset++] = 6; // TOOL + + AString tool; + MakeUserAgentString(&tool); + + data[offset++] = tool.size(); + + memcpy(&data[offset], tool.c_str(), tool.size()); + offset += tool.size(); + + data[offset++] = 0; + + if ((offset % 4) > 0) { + size_t count = 4 - (offset % 4); + switch (count) { + case 3: + data[offset++] = 0; + case 2: + data[offset++] = 0; + case 1: + data[offset++] = 0; + } + } + + size_t numWords = (offset / 4) - 1; + data[2] = numWords >> 8; + data[3] = numWords & 0xff; + + buffer->setRange(buffer->offset(), buffer->size() + offset); + } + + // In case we're behind NAT, fire off two UDP packets to the remote + // rtp/rtcp ports to poke a hole into the firewall for future incoming + // packets. We're going to send an RR/SDES RTCP packet to both of them. + void pokeAHole(int rtpSocket, int rtcpSocket, const AString &transport) { + AString source; + AString server_port; + if (!GetAttribute(transport.c_str(), + "source", + &source) + || !GetAttribute(transport.c_str(), + "server_port", + &server_port)) { + return; + } + + int rtpPort, rtcpPort; + if (sscanf(server_port.c_str(), "%d-%d", &rtpPort, &rtcpPort) != 2 + || rtpPort <= 0 || rtpPort > 65535 + || rtcpPort <=0 || rtcpPort > 65535 + || rtcpPort != rtpPort + 1 + || (rtpPort & 1) != 0) { + return; + } + + struct sockaddr_in addr; + memset(addr.sin_zero, 0, sizeof(addr.sin_zero)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = inet_addr(source.c_str()); + + if (addr.sin_addr.s_addr == INADDR_NONE) { + return; + } + + // Make up an RR/SDES RTCP packet. + sp<ABuffer> buf = new ABuffer(65536); + buf->setRange(0, 0); + addRR(buf); + addSDES(rtpSocket, buf); + + addr.sin_port = htons(rtpPort); + + ssize_t n = sendto( + rtpSocket, buf->data(), buf->size(), 0, + (const sockaddr *)&addr, sizeof(addr)); + CHECK_EQ(n, (ssize_t)buf->size()); + + addr.sin_port = htons(rtcpPort); + + n = sendto( + rtcpSocket, buf->data(), buf->size(), 0, + (const sockaddr *)&addr, sizeof(addr)); + CHECK_EQ(n, (ssize_t)buf->size()); + + LOGV("successfully poked holes."); + } + virtual void onMessageReceived(const sp<AMessage> &msg) { switch (msg->what()) { case 'conn': @@ -285,6 +427,17 @@ struct MyHandler : public AHandler { sp<AMessage> notify = new AMessage('accu', id()); notify->setSize("track-index", trackIndex); + i = response->mHeaders.indexOfKey("transport"); + CHECK_GE(i, 0); + + if (!track->mUsingInterleavedTCP) { + AString transport = response->mHeaders.valueAt(i); + + pokeAHole(track->mRTPSocket, + track->mRTCPSocket, + transport); + } + mRTPConn->addStream( track->mRTPSocket, track->mRTCPSocket, mSessionDesc, index, diff --git a/services/java/com/android/server/location/GpsLocationProvider.java b/services/java/com/android/server/location/GpsLocationProvider.java index 87271e73fe59..f9c167943981 100755 --- a/services/java/com/android/server/location/GpsLocationProvider.java +++ b/services/java/com/android/server/location/GpsLocationProvider.java @@ -493,6 +493,11 @@ public class GpsLocationProvider implements LocationProviderInterface { + " info: " + info); } + if (info != null) { + native_update_network_state(info.isConnected(), info.getType(), + info.isRoaming(), info.getExtraInfo()); + } + if (info != null && info.getType() == ConnectivityManager.TYPE_MOBILE_SUPL && mAGpsDataConnectionState == AGPS_DATA_CONNECTION_OPENING) { String apnName = info.getExtraInfo(); @@ -1601,4 +1606,7 @@ public class GpsLocationProvider implements LocationProviderInterface { private native void native_agps_set_ref_location_cellid(int type, int mcc, int mnc, int lac, int cid); private native void native_agps_set_id(int type, String setid); + + private native void native_update_network_state(boolean connected, int type, + boolean roaming, String extraInfo); } diff --git a/services/jni/com_android_server_location_GpsLocationProvider.cpp b/services/jni/com_android_server_location_GpsLocationProvider.cpp index bd722d73b679..43e8467fb6dd 100755 --- a/services/jni/com_android_server_location_GpsLocationProvider.cpp +++ b/services/jni/com_android_server_location_GpsLocationProvider.cpp @@ -586,6 +586,23 @@ static jstring android_location_GpsLocationProvider_get_internal_state(JNIEnv* e return result; } +static void android_location_GpsLocationProvider_update_network_state(JNIEnv* env, jobject obj, + jboolean connected, int type, jboolean roaming, jstring extraInfo) +{ + const AGpsRilInterface* interface = GetAGpsRilInterface(env, obj); + if (interface && + (interface->size > ((char *)&interface->update_network_state - (char *)&interface)) && + interface->update_network_state) { + if (extraInfo) { + const char *extraInfoStr = env->GetStringUTFChars(extraInfo, NULL); + interface->update_network_state(connected, type, roaming, extraInfoStr); + env->ReleaseStringUTFChars(extraInfo, extraInfoStr); + } else { + interface->update_network_state(connected, type, roaming, NULL); + } + } +} + static JNINativeMethod sMethods[] = { /* name, signature, funcPtr */ {"class_init_native", "()V", (void *)android_location_GpsLocationProvider_class_init_native}, @@ -611,6 +628,7 @@ static JNINativeMethod sMethods[] = { {"native_send_ni_response", "(II)V", (void*)android_location_GpsLocationProvider_send_ni_response}, {"native_agps_ni_message", "([BI)V", (void *)android_location_GpsLocationProvider_agps_send_ni_message}, {"native_get_internal_state", "()Ljava/lang/String;", (void*)android_location_GpsLocationProvider_get_internal_state}, + {"native_update_network_state", "(ZIZLjava/lang/String;)V", (void*)android_location_GpsLocationProvider_update_network_state }, }; int register_android_server_location_GpsLocationProvider(JNIEnv* env) diff --git a/services/surfaceflinger/MessageQueue.cpp b/services/surfaceflinger/MessageQueue.cpp index d668e88d471f..4fb1e6133b1c 100644 --- a/services/surfaceflinger/MessageQueue.cpp +++ b/services/surfaceflinger/MessageQueue.cpp @@ -91,17 +91,21 @@ sp<MessageBase> MessageQueue::waitMessage(nsecs_t timeout) mMessages.remove(cur); break; } - if (timeout>=0 && timeoutTime < now) { - // we timed-out, return a NULL message - result = 0; - break; - } nextEventTime = result->when; result = 0; } - if (timeout >= 0 && nextEventTime > 0) { - if (nextEventTime > timeoutTime) { + if (timeout >= 0) { + if (timeoutTime < now) { + // we timed-out, return a NULL message + result = 0; + break; + } + if (nextEventTime > 0) { + if (nextEventTime > timeoutTime) { + nextEventTime = timeoutTime; + } + } else { nextEventTime = timeoutTime; } } |