forked from mirrors/gecko-dev
Bug 1902077 - Work around a battery usage misattribution bug in Android 14. r=jolin,geckoview-reviewers,owlish a=RyanVM
Android is getting confused about which process is owning a media resource; in different places it stores either our media process's pid or our tab process's pid. Then, when our processes shut down (or rather when they get killed by Android), this confusion leads Android to do improper cleanup of its video resource accounting. This causes it to keep increasing the "video" time for Firefox (in `adb shell dumpsys batterystats --usage`) even while no Firefox processes are running. This in turn causes the "Battery" UI in Android's system preferences to show large values for Firefox. To work around this attribution error, we try to ensure that Android tracks the same PID in all the places. Specifically, the problem is that the constructor of `android::MediaCodec::ResourceManagerServiceProxy::ResourceManagerServiceProxy` is getting the owning PID from `AIBinder_getCallingPid()`. The Firefox media process calls `MediaCodec.createByCodecName` under a binder transaction from the tab process, specifically while the tab process is calling `ICodec$Stub$Proxy.configure` inside `CodecProxy.init`. This fix makes it so that `AIBinder_getCallingPid()` returns the media process's PID, by wrapping the call to `MediaCodec.createByCodecName` in calls to `Binder.clearCallingIdentity` / `Binder.restoreCallingIdentity`. The Android documentation says the following about `clearCallingIdentity`: > This can be useful if, while handling an incoming call, you will be calling > on interfaces of other objects that may be local to your process and need to > do permission checks on the calls coming into them (so they will check the > permission of your own local process, and not whatever process originally > called you). This matches what we're trying to do here quite well. --- Firefox media process stack showing MediaCodec.createByCodecName getting into `AIBinder_getCallingPid()`: ``` AIBinder_getCallingPid android::MediaCodec::ResourceManagerServiceProxy::ResourceManagerServiceProxy(int, unsigned int, std::__1::shared_ptr<aidl::android::media::IResourceManagerClient> const&, android::MediaCodec*)[libstagefright.so] android::MediaCodec::MediaCodec(android::sp<android::ALooper> const&, int, unsigned int, std::__1::function<android::sp<android::CodecBase>(android::AString const&, char const*)>, std::__1::function<int (android::AString const&, android::sp<android::MediaCodecInfo>*)>) android::MediaCodec::CreateByComponentName(android::sp<android::ALooper> const&, android::AString const&, int*, int, unsigned int) android::JMediaCodec::JMediaCodec(_JNIEnv*, _jobject*, char const*, bool, bool, int, int) android_media_MediaCodec_native_setup(_JNIEnv*, _jobject*, _jstring*, unsigned char, unsigned char, int, int) android.media.MediaCodec.<init> android.media.MediaCodec.<init> android.media.MediaCodec.createByCodecName org.mozilla.gecko.media.LollipopAsyncCodec.<init> ``` Firefox tab process stack showing `ICodec$Stub$Proxy.configure` binder call: ``` _ioctl ioctl android::IPCThreadState::talkWithDriver(bool) android::IPCThreadState::waitForResponse(android::Parcel*, int*) android::IPCThreadState::transact(int, unsigned int, android::Parcel const&, android::Parcel*, unsigned int) android::BpBinder::transact(unsigned int, android::Parcel const&, android::Parcel*, unsigned int) android_os_BinderProxy_transact(_JNIEnv*, _jobject*, int, _jobject*, _jobject*, int) art_quick_generic_jni_trampoline art_quick_invoke_stub android.os.BinderProxy.transact org.mozilla.gecko.media.ICodec$Stub$Proxy.configure org.mozilla.gecko.media.CodecProxy.init org.mozilla.gecko.media.RemoteManager.createCodec org.mozilla.gecko.media.CodecProxy.create mozilla::java::CodecProxy::Create mozilla::RemoteVideoDecoder::Init() ``` Differential Revision: https://phabricator.services.mozilla.com/D214316
This commit is contained in:
parent
a0cbf8098c
commit
f97be7a62c
1 changed files with 13 additions and 1 deletions
|
|
@ -8,6 +8,7 @@ import android.media.MediaCodec;
|
|||
import android.media.MediaCodecInfo.CodecCapabilities;
|
||||
import android.media.MediaCrypto;
|
||||
import android.media.MediaFormat;
|
||||
import android.os.Binder;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
|
|
@ -134,7 +135,18 @@ import org.mozilla.gecko.util.HardwareCodecCapabilityUtils;
|
|||
}
|
||||
|
||||
/* package */ LollipopAsyncCodec(final String name) throws IOException {
|
||||
mCodec = MediaCodec.createByCodecName(name);
|
||||
// Create the codec.
|
||||
// We wrap the call to MediaCodec.createByCodecName in a pair of
|
||||
// clearCallingIdentity / restoreCallingIdentity, so that the resource
|
||||
// gets attributed to this process and not to whichever process was calling us.
|
||||
// This works around a battery usage attribution bug in Android 14+,
|
||||
// see bug 1902077.
|
||||
final long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
mCodec = MediaCodec.createByCodecName(name);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
Loading…
Reference in a new issue