How to fix ExoPlayer error 'native window cannot handle protected buffers' - android

I keep getting an error when pausing ExoPlayer and putting my app in the background. The stream contains Widevine protected content and ads that are inserted on the server side.
I suspect this mixture of protected and unprotected content to be causing the error but have no idea where to start. Putting the app in the background and resuming it actually works once during the unprotected preroll ad but fails when trying it a second time in the main content.
SurfaceUtils logs the following message: native window cannot handle protected buffers: the consumer should either be a hardware composer or support hardware protection.
Does someone know what this actually means? Unfortunately I am not too familiar with the inner workings of ExoPlayer.
The code in SurfaceUtils.cpp that returns the error might be helpful here:
// Make sure to check whether either Stagefright or the video decoder
// requested protected buffers.
if (usage & GRALLOC_USAGE_PROTECTED) {
// Check if the ANativeWindow sends images directly to SurfaceFlinger.
int queuesToNativeWindow = 0;
err = nativeWindow->query(
nativeWindow, NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER, &queuesToNativeWindow);
if (err != NO_ERROR) {
ALOGE("error authenticating native window: %s (%d)", strerror(-err), -err);
return err;
}
// Check if the consumer end of the ANativeWindow can handle protected content.
int isConsumerProtected = 0;
err = nativeWindow->query(
nativeWindow, NATIVE_WINDOW_CONSUMER_IS_PROTECTED, &isConsumerProtected);
if (err != NO_ERROR) {
ALOGE("error query native window: %s (%d)", strerror(-err), -err);
return err;
}
// Deny queuing into native window if neither condition is satisfied.
if (queuesToNativeWindow != 1 && isConsumerProtected != 1) {
ALOGE("native window cannot handle protected buffers: the consumer should either be a hardware composer or support hardware protection");
return PERMISSION_DENIED;
}
}

Related

Get mangled name of function when using .so shared library from Android c++ side? (libAudioFlinger.so)

i have been working on this problem for 2 weeks now, i have integrate C++ code into my Voip call recording app, the code is supposed to take care of forcefully setting Input_source of mediaRecorder to same one as from the Voip Call (in my case it is input_source=7 / Voice_Communication).
In order to achieve my goal i load shared library : libaudioflinger.so and attempt to reach SetParameters function, as can be seen from the snipet below :
handleLibAudioFlinger = dlopen("libaudioflinger.so", RTLD_LAZY | RTLD_GLOBAL);
if (handleLibAudioFlinger != NULL) {
func = dlsym(handleLibAudioFlinger, "setParameters"); // i do not know the mangled name of
SetParameters function
if (func != NULL) {
__android_log_print(ANDROID_LOG_ERROR, "TRACKERS", "%s", "Function is not null");
result = 0;
}
audioSetParameters = (lasp) func;
} else {
__android_log_print(ANDROID_LOG_ERROR, "TRACKERS", "%s", "Function is null");
result = -1;
}
dlopen does not return null, but dlsym does, reason is that i need to have the exact mangled name of the function setParameters from AudioFlinger.cpp As in Android source code.
i am new to handling android c++ code and dealing with shared libraries,etc... if someone can tell me step by step how to get correct mangled name for the function that i need?

How to pragmatically set a videoCodec to LinphoneCore in Android?

I am currently Developing a VoIP Android Application, and for VoIP support, I am using an Open source library Linphone.
Currently voice calling is happening, but video calling is not happening. After analyzing for a while, I came to know that by default when the app is loaded, the LinphoneCore library is using the H264 video codec.
But the VOIP Asterik server is configured with the VP8 video codec. I cannot change the video codec, which is configured in the server. Hence due to a codec mismatch, video data is not going.
So how can I set manually the video codec to VP8 from my app to LinphoneCore once the app is loaded?
To set videoCodec to LinphoneCore, what you can do is , once your LinphoneCore is ready, you can just Retrieve the VideoCodec Payload that it supports and then set a particular payload and disable others as shown below in the code.
private void enableVp8Codec () {
LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
if (lc != null) {
PayloadType[] lPayLoadArr = lc.getVideoCodecs();
for (final PayloadType pt : lPayLoadArr) {
try {
if (pt.getMime().equals("VP8")) {
lc.enablePayloadType(pt, true);
} else {
lc.enablePayloadType(pt, false);
}
} catch (LinphoneCoreException e) {
Log.e("tag",e.getMessage());
}
}
}
}
This method you can probably call in onResume of your Activity

odata4j requests metadata too many times

I use the odata4j library to access a WCF Data Service.
This is how I call a Service Method from my Android code:
OQueryRequest<OEntity> l = consumer.getEntities("GetDataList")
.custom("dataId", String.format("'%s'", actualData.ID))
.orderBy("Name").skip(0).top(200);
I checked it with WireShark, and I see that every method call is preceded with 2 calls of metadata information request:
Why? Are they essential? The metadata information is quite heavy, it shouldn't request is every time (not to mention 2 times).
What should I do to prevent odata4j from requesting metadata information so many times?
I found in the source code where the 'extra' request happens (in odata4j/odata4j-core/src/main/java/org/odata4j/consumer/AbstractODataConsumer.java ):
#Override
public EdmEntitySet findEdmEntitySet(String entitySetName) {
EdmEntitySet rt = super.findEdmEntitySet(entitySetName);
if (rt == null && delegate != EdmDataServices.EMPTY) {
refreshDelegate();
rt = super.findEdmEntitySet(entitySetName);
}
return rt;
}
It seems that if the entity set can't be found, the consumer creates an extra roundtrip to the server to get the metadata again (by calling refreshDelegate()):
private void refreshDelegate() {
ODataClientRequest request = ODataClientRequest.get(AbstractODataConsumer.this.getServiceRootUri() + "$metadata");
try {
delegate = AbstractODataConsumer.this.getClient().getMetadata(request);
} catch (ODataProducerException e) {
// to support services that do not expose metadata information
delegate = EdmDataServices.EMPTY;
}
}
I don't quite understand why: maybe it assumes that the server has changed and a new version of the metadata is available so it tries again.
If it fails then it tries to find a function with the given name.
Personally I don't consider this very effective unless the server side is so volatile that it changes between calls.
So, if you have no changing metadata on the server, it is safe to remove the check for the entitySet and let it return as a null:
#Override
public EdmEntitySet findEdmEntitySet(String entitySetName) {
EdmEntitySet rt = super.findEdmEntitySet(entitySetName);
//if (rt == null && delegate != EdmDataServices.EMPTY) {
// refreshDelegate();
// rt = super.findEdmEntitySet(entitySetName);
//}
return rt; //if it is null, then the search for a function will commence
}

How should GATT_CMD_STARTED (status=134) be interpreted?

I'm working on an android app where I need to communicate with a bluetooth LE device and in the middle of the communication I receive a callback:
onCharacteristicWrite()
...which is expected. But the status of the operation is 134 instead of 0 (=success).
This GATT status constant is not defined in the official API but here is a translation in one of many unofficial lists:
public static final int GATT_CMD_STARTED = 134;
See: https://code.google.com/r/naranjomanuel-opensource-broadcom-ble/source/browse/framework/java/src/com/broadcom/bt/service/gatt/GattConstants.java?r=983950f9b35407446bf082633d70c7655c206d22
The consequence, that I can see, in my app is that I do not get an expected callback to:
onCharacteristicChanged()
Does anybody know what GATT_CMD_STARTED means? Is it an error?
The description of the following function taken from the bludroid sources hint that something is not working correctly in your GATT server.
Commands seem to "queue up" there, as there must be pending requests or value confirmations as hinted in the comment before the if(...) clause.
It might be worth checking what exactly is going on before you do the writeCharacteristic(...) as it seems to not finish correctly or create hiccups in your server.
/*******************************************************************************
**
** Function attp_cl_send_cmd
**
** Description Send a ATT command or enqueue it.
**
** Returns GATT_SUCCESS if command sent
** GATT_CONGESTED if command sent but channel congested
** GATT_CMD_STARTED if command queue up in GATT
** GATT_ERROR if command sending failure
**
*******************************************************************************/
tGATT_STATUS attp_cl_send_cmd(tGATT_TCB *p_tcb, UINT16 clcb_idx, UINT8 cmd_code, BT_HDR *p_cmd)
{
tGATT_STATUS att_ret = GATT_SUCCESS;
if (p_tcb != NULL)
{
cmd_code &= ~GATT_AUTH_SIGN_MASK;
/* no pending request or value confirmation */
if (p_tcb->pending_cl_req == p_tcb->next_slot_inq ||
cmd_code == GATT_HANDLE_VALUE_CONF)
{
att_ret = attp_send_msg_to_l2cap(p_tcb, p_cmd);
if (att_ret == GATT_CONGESTED || att_ret == GATT_SUCCESS)
{
/* do not enq cmd if handle value confirmation or set request */
if (cmd_code != GATT_HANDLE_VALUE_CONF && cmd_code != GATT_CMD_WRITE)
{
gatt_start_rsp_timer (clcb_idx);
gatt_cmd_enq(p_tcb, clcb_idx, FALSE, cmd_code, NULL);
}
}
else
att_ret = GATT_INTERNAL_ERROR;
}
else
{
att_ret = GATT_CMD_STARTED;
gatt_cmd_enq(p_tcb, clcb_idx, TRUE, cmd_code, p_cmd);
}
}
else
att_ret = GATT_ERROR;
return att_ret;
}
Starts at line 469 in android sources.
The native GATT error and statuscodes can be found here.

Android SSL Error Handshake Failed

I have an android application that works on my home network and does not have these handshake errors. However when sending this app over to my client and testing it through their wifi network I get these logs.
E/chromium(15135): external/chromium/net/socket/ssl_client_socket_openssl.cc:792: [1211/175912:ERROR:ssl_client_socket_openssl.cc(792)] handshake failed; returned 0, SSL error code 5, net_error -107
W/chromium(15135): external/chromium/net/http/http_stream_factory_impl_job.cc:865: [1211/175912:WARNING:http_stream_factory_impl_job.cc(865)] Falling back to SSLv3 because host is TLS intolerant:
I have https URLS loaded in an android webview inside my application. I have no other information aside from these errors. Do you guys have any idea why this happens on a specific network, I am really out of ideas right now.
Recently I occurred a similar error during my test on connecting the specific server:
handshake failed; returned -1, SSL error code 1, net_error -103
I find some useful reason by searching from chromium source code,which indicates the meaning of ret code.Maybe it can help you find the reason.
SSL error code 5:
chromium//src/third_party/boringssl/src/include/openssl/ssl.h
/*
SSL_ERROR_SYSCALL indicates the operation failed externally to the library.
The caller should consult the system-specific error mechanism. This is
typically |errno| but may be something custom if using a custom |BIO|. It
may also be signaled if the transport returned EOF, in which case the
operation's return value will be zero.
*/
define SSL_ERROR_SYSCALL 5
net_error -107
// An SSL protocol error occurred.
NET_ERROR(SSL_PROTOCOL_ERROR, -107)
if you want to find more detail,the main function which print this log as below:
chromium//src/net/socket/ssl_server_socket_impl.cc
int SSLServerSocketImpl::DoHandshake() {
crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
int net_error = OK;
int rv = SSL_do_handshake(ssl_.get());
if (rv == 1) {
completed_handshake_ = true;
// The results of SSL_get_peer_certificate() must be explicitly freed.
bssl::UniquePtr<X509> cert(SSL_get_peer_certificate(ssl_.get()));
if (cert) {
// The caller does not take ownership of SSL_get_peer_cert_chain's
// results.
STACK_OF(X509)* chain = SSL_get_peer_cert_chain(ssl_.get());
client_cert_ = CreateX509Certificate(cert.get(), chain);
if (!client_cert_.get())
return ERR_SSL_CLIENT_AUTH_CERT_BAD_FORMAT;
}
} else {
int ssl_error = SSL_get_error(ssl_.get(), rv);
OpenSSLErrorInfo error_info;
net_error = MapOpenSSLErrorWithDetails(ssl_error, err_tracer,
&error_info);
// SSL_R_CERTIFICATE_VERIFY_FAILED's mapping is different between client and
// server.
if (ERR_GET_LIB(error_info.error_code) == ERR_LIB_SSL &&
ERR_GET_REASON(error_info.error_code) ==
SSL_R_CERTIFICATE_VERIFY_FAILED) {
net_error = ERR_BAD_SSL_CLIENT_AUTH_CERT;
}
// If not done, stay in this state
if (net_error == ERR_IO_PENDING) {
GotoState(STATE_HANDSHAKE);
} else {
LOG(ERROR) << "handshake failed; returned " << rv << ", SSL error code "
<< ssl_error << ", net_error " << net_error;
net_log_.AddEvent(
NetLogEventType::SSL_HANDSHAKE_ERROR,
CreateNetLogOpenSSLErrorCallback(net_error, ssl_error,
error_info));
}
}
return net_error;
}

Categories

Resources