Skip to content

Commit 7017e48

Browse files
Jeff BrownAndroid (Google) Code Review
authored andcommitted
Merge "Add support for Wifi display." into jb-mr1-dev
2 parents cd62059 + cbad976 commit 7017e48

File tree

19 files changed

+1441
-138
lines changed

19 files changed

+1441
-138
lines changed

core/java/android/view/Surface.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ private static native Bitmap nativeScreenshot(IBinder displayToken,
259259
private static native IBinder nativeGetBuiltInDisplay(int physicalDisplayId);
260260
private static native IBinder nativeCreateDisplay(String name);
261261
private static native void nativeSetDisplaySurface(
262-
IBinder displayToken, SurfaceTexture surfaceTexture);
262+
IBinder displayToken, Surface surface);
263263
private static native void nativeSetDisplayLayerStack(
264264
IBinder displayToken, int layerStack);
265265
private static native void nativeSetDisplayProjection(
@@ -597,11 +597,11 @@ public static IBinder createDisplay(String name) {
597597
}
598598

599599
/** @hide */
600-
public static void setDisplaySurface(IBinder displayToken, SurfaceTexture surfaceTexture) {
600+
public static void setDisplaySurface(IBinder displayToken, Surface surface) {
601601
if (displayToken == null) {
602602
throw new IllegalArgumentException("displayToken must not be null");
603603
}
604-
nativeSetDisplaySurface(displayToken, surfaceTexture);
604+
nativeSetDisplaySurface(displayToken, surface);
605605
}
606606

607607
/** @hide */
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright (C) 2012 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.android.internal.util;
18+
19+
import android.os.Handler;
20+
21+
import java.io.PrintWriter;
22+
import java.io.StringWriter;
23+
24+
/**
25+
* Helper functions for dumping the state of system services.
26+
*/
27+
public final class DumpUtils {
28+
private DumpUtils() {
29+
}
30+
31+
/**
32+
* Helper for dumping state owned by a handler thread.
33+
*
34+
* Because the caller might be holding an important lock that the handler is
35+
* trying to acquire, we use a short timeout to avoid deadlocks. The process
36+
* is inelegant but this function is only used for debugging purposes.
37+
*/
38+
public static void dumpAsync(Handler handler, final Dump dump, PrintWriter pw, long timeout) {
39+
final StringWriter sw = new StringWriter();
40+
if (handler.runWithScissors(new Runnable() {
41+
@Override
42+
public void run() {
43+
PrintWriter lpw = new PrintWriter(sw);
44+
dump.dump(lpw);
45+
lpw.close();
46+
}
47+
}, timeout)) {
48+
pw.print(sw.toString());
49+
} else {
50+
pw.println("... timed out");
51+
}
52+
}
53+
54+
public interface Dump {
55+
void dump(PrintWriter pw);
56+
}
57+
}

core/java/com/android/internal/util/IndentingPrintWriter.java

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public class IndentingPrintWriter extends PrintWriter {
2828
private final String mIndent;
2929

3030
private StringBuilder mBuilder = new StringBuilder();
31-
private String mCurrent = new String();
31+
private char[] mCurrent;
3232
private boolean mEmptyLine = true;
3333

3434
public IndentingPrintWriter(Writer writer, String indent) {
@@ -38,30 +38,48 @@ public IndentingPrintWriter(Writer writer, String indent) {
3838

3939
public void increaseIndent() {
4040
mBuilder.append(mIndent);
41-
mCurrent = mBuilder.toString();
41+
mCurrent = null;
4242
}
4343

4444
public void decreaseIndent() {
4545
mBuilder.delete(0, mIndent.length());
46-
mCurrent = mBuilder.toString();
46+
mCurrent = null;
4747
}
4848

4949
public void printPair(String key, Object value) {
5050
print(key + "=" + String.valueOf(value) + " ");
5151
}
5252

5353
@Override
54-
public void println() {
55-
super.println();
56-
mEmptyLine = true;
54+
public void write(char[] buf, int offset, int count) {
55+
final int bufferEnd = offset + count;
56+
int lineStart = offset;
57+
int lineEnd = offset;
58+
while (lineEnd < bufferEnd) {
59+
char ch = buf[lineEnd++];
60+
if (ch == '\n') {
61+
writeIndent();
62+
super.write(buf, lineStart, lineEnd - lineStart);
63+
lineStart = lineEnd;
64+
mEmptyLine = true;
65+
}
66+
}
67+
68+
if (lineStart != lineEnd) {
69+
writeIndent();
70+
super.write(buf, lineStart, lineEnd - lineStart);
71+
}
5772
}
5873

59-
@Override
60-
public void write(char[] buf, int offset, int count) {
74+
private void writeIndent() {
6175
if (mEmptyLine) {
6276
mEmptyLine = false;
63-
super.print(mCurrent);
77+
if (mBuilder.length() != 0) {
78+
if (mCurrent == null) {
79+
mCurrent = mBuilder.toString().toCharArray();
80+
}
81+
super.write(mCurrent, 0, mCurrent.length);
82+
}
6483
}
65-
super.write(buf, offset, count);
6684
}
6785
}

core/jni/Android.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ LOCAL_SRC_FILES:= \
126126
android_media_AudioSystem.cpp \
127127
android_media_AudioTrack.cpp \
128128
android_media_JetPlayer.cpp \
129+
android_media_RemoteDisplay.cpp \
129130
android_media_ToneGenerator.cpp \
130131
android_hardware_Camera.cpp \
131132
android_hardware_SensorManager.cpp \

core/jni/AndroidRuntime.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ extern int register_android_backup_BackupHelperDispatcher(JNIEnv *env);
160160
extern int register_android_app_backup_FullBackup(JNIEnv *env);
161161
extern int register_android_app_ActivityThread(JNIEnv *env);
162162
extern int register_android_app_NativeActivity(JNIEnv *env);
163+
extern int register_android_media_RemoteDisplay(JNIEnv *env);
163164
extern int register_android_view_InputChannel(JNIEnv* env);
164165
extern int register_android_view_InputDevice(JNIEnv* env);
165166
extern int register_android_view_InputEventReceiver(JNIEnv* env);
@@ -1161,6 +1162,7 @@ static const RegJNIRec gRegJNI[] = {
11611162
REG_JNI(register_android_media_AudioSystem),
11621163
REG_JNI(register_android_media_AudioTrack),
11631164
REG_JNI(register_android_media_JetPlayer),
1165+
REG_JNI(register_android_media_RemoteDisplay),
11641166
REG_JNI(register_android_media_ToneGenerator),
11651167

11661168
REG_JNI(register_android_opengl_classes),
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
/*
2+
* Copyright (C) 2012 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#define LOG_TAG "RemoteDisplay"
18+
19+
#include "jni.h"
20+
#include "JNIHelp.h"
21+
22+
#include "android_os_Parcel.h"
23+
#include "android_util_Binder.h"
24+
25+
#include <android_runtime/AndroidRuntime.h>
26+
#include <android_runtime/android_view_Surface.h>
27+
28+
#include <binder/IServiceManager.h>
29+
30+
#include <gui/ISurfaceTexture.h>
31+
32+
#include <media/IMediaPlayerService.h>
33+
#include <media/IRemoteDisplay.h>
34+
#include <media/IRemoteDisplayClient.h>
35+
36+
#include <utils/Log.h>
37+
38+
#include <ScopedUtfChars.h>
39+
40+
namespace android {
41+
42+
static struct {
43+
jmethodID notifyDisplayConnected;
44+
jmethodID notifyDisplayDisconnected;
45+
jmethodID notifyDisplayError;
46+
} gRemoteDisplayClassInfo;
47+
48+
// ----------------------------------------------------------------------------
49+
50+
class NativeRemoteDisplayClient : public BnRemoteDisplayClient {
51+
public:
52+
NativeRemoteDisplayClient(JNIEnv* env, jobject remoteDisplayObj) :
53+
mRemoteDisplayObjGlobal(env->NewGlobalRef(remoteDisplayObj)) {
54+
}
55+
56+
protected:
57+
~NativeRemoteDisplayClient() {
58+
JNIEnv* env = AndroidRuntime::getJNIEnv();
59+
env->DeleteGlobalRef(mRemoteDisplayObjGlobal);
60+
}
61+
62+
public:
63+
virtual void onDisplayConnected(const sp<ISurfaceTexture>& surfaceTexture,
64+
uint32_t width, uint32_t height, uint32_t flags) {
65+
JNIEnv* env = AndroidRuntime::getJNIEnv();
66+
67+
jobject surfaceObj = android_view_Surface_createFromISurfaceTexture(env, surfaceTexture);
68+
if (surfaceObj == NULL) {
69+
ALOGE("Could not create Surface from surface texture %p provided by media server.",
70+
surfaceTexture.get());
71+
return;
72+
}
73+
74+
env->CallVoidMethod(mRemoteDisplayObjGlobal,
75+
gRemoteDisplayClassInfo.notifyDisplayConnected,
76+
surfaceObj, width, height, flags);
77+
env->DeleteLocalRef(surfaceObj);
78+
checkAndClearExceptionFromCallback(env, "notifyDisplayConnected");
79+
}
80+
81+
virtual void onDisplayDisconnected() {
82+
JNIEnv* env = AndroidRuntime::getJNIEnv();
83+
84+
env->CallVoidMethod(mRemoteDisplayObjGlobal,
85+
gRemoteDisplayClassInfo.notifyDisplayDisconnected);
86+
checkAndClearExceptionFromCallback(env, "notifyDisplayDisconnected");
87+
}
88+
89+
virtual void onDisplayError(int32_t error) {
90+
JNIEnv* env = AndroidRuntime::getJNIEnv();
91+
92+
env->CallVoidMethod(mRemoteDisplayObjGlobal,
93+
gRemoteDisplayClassInfo.notifyDisplayError, error);
94+
checkAndClearExceptionFromCallback(env, "notifyDisplayError");
95+
}
96+
97+
private:
98+
jobject mRemoteDisplayObjGlobal;
99+
100+
static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
101+
if (env->ExceptionCheck()) {
102+
ALOGE("An exception was thrown by callback '%s'.", methodName);
103+
LOGE_EX(env);
104+
env->ExceptionClear();
105+
}
106+
}
107+
};
108+
109+
class NativeRemoteDisplay {
110+
public:
111+
NativeRemoteDisplay(const sp<IRemoteDisplay>& display,
112+
const sp<NativeRemoteDisplayClient>& client) :
113+
mDisplay(display), mClient(client) {
114+
}
115+
116+
~NativeRemoteDisplay() {
117+
mDisplay->dispose();
118+
}
119+
120+
private:
121+
sp<IRemoteDisplay> mDisplay;
122+
sp<NativeRemoteDisplayClient> mClient;
123+
};
124+
125+
126+
// ----------------------------------------------------------------------------
127+
128+
static jint nativeListen(JNIEnv* env, jobject remoteDisplayObj, jstring ifaceStr) {
129+
ScopedUtfChars iface(env, ifaceStr);
130+
131+
sp<IServiceManager> sm = defaultServiceManager();
132+
sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(
133+
sm->getService(String16("media.player")));
134+
if (service == NULL) {
135+
ALOGE("Could not obtain IMediaPlayerService from service manager");
136+
return 0;
137+
}
138+
139+
sp<NativeRemoteDisplayClient> client(new NativeRemoteDisplayClient(env, remoteDisplayObj));
140+
sp<IRemoteDisplay> display = service->listenForRemoteDisplay(
141+
client, String8(iface.c_str()));
142+
if (display == NULL) {
143+
ALOGE("Media player service rejected request to listen for remote display '%s'.",
144+
iface.c_str());
145+
return 0;
146+
}
147+
148+
NativeRemoteDisplay* wrapper = new NativeRemoteDisplay(display, client);
149+
return reinterpret_cast<jint>(wrapper);
150+
}
151+
152+
static void nativeDispose(JNIEnv* env, jobject remoteDisplayObj, jint ptr) {
153+
NativeRemoteDisplay* wrapper = reinterpret_cast<NativeRemoteDisplay*>(ptr);
154+
delete wrapper;
155+
}
156+
157+
// ----------------------------------------------------------------------------
158+
159+
static JNINativeMethod gMethods[] = {
160+
{"nativeListen", "(Ljava/lang/String;)I",
161+
(void*)nativeListen },
162+
{"nativeDispose", "(I)V",
163+
(void*)nativeDispose },
164+
};
165+
166+
int register_android_media_RemoteDisplay(JNIEnv* env)
167+
{
168+
int err = AndroidRuntime::registerNativeMethods(env, "android/media/RemoteDisplay",
169+
gMethods, NELEM(gMethods));
170+
171+
jclass clazz = env->FindClass("android/media/RemoteDisplay");
172+
gRemoteDisplayClassInfo.notifyDisplayConnected =
173+
env->GetMethodID(clazz, "notifyDisplayConnected",
174+
"(Landroid/view/Surface;III)V");
175+
gRemoteDisplayClassInfo.notifyDisplayDisconnected =
176+
env->GetMethodID(clazz, "notifyDisplayDisconnected", "()V");
177+
gRemoteDisplayClassInfo.notifyDisplayError =
178+
env->GetMethodID(clazz, "notifyDisplayError", "(I)V");
179+
return err;
180+
}
181+
182+
};

0 commit comments

Comments
 (0)