Add FakeContext.getContentResolver()
This avoids the following error on some devices: Given calling package android does not match caller's uid 2000 Refs #4639 comment <https://github.com/Genymobile/scrcpy/issues/4639#issuecomment-2466081589> Fixes #4639 <https://github.com/Genymobile/scrcpy/issues/4639> PR #5476 <https://github.com/Genymobile/scrcpy/pull/5476> Signed-off-by: Romain Vimont <rom@rom1v.com>
This commit is contained in:
parent
c0e2e27cf9
commit
91373d906b
@ -50,6 +50,11 @@ cd "$SERVER_DIR/src/main/aidl"
|
||||
android/content/IOnPrimaryClipChangedListener.aidl
|
||||
"$BUILD_TOOLS_DIR/aidl" -o"$GEN_DIR" -I. android/view/IDisplayFoldListener.aidl
|
||||
|
||||
# Fake sources to expose hidden Android types to the project
|
||||
FAKE_SRC=( \
|
||||
android/content/*java \
|
||||
)
|
||||
|
||||
SRC=( \
|
||||
com/genymobile/scrcpy/*.java \
|
||||
com/genymobile/scrcpy/audio/*.java \
|
||||
@ -72,6 +77,7 @@ javac -encoding UTF-8 -bootclasspath "$ANDROID_JAR" \
|
||||
-cp "$LAMBDA_JAR:$GEN_DIR" \
|
||||
-d "$CLASSES_DIR" \
|
||||
-source 1.8 -target 1.8 \
|
||||
${FAKE_SRC[@]} \
|
||||
${SRC[@]}
|
||||
|
||||
echo "Dexing..."
|
||||
|
@ -0,0 +1,5 @@
|
||||
package android.content;
|
||||
|
||||
public interface IContentProvider {
|
||||
// android.content.IContentProvider is hidden, this is a fake one to expose the type to the project
|
||||
}
|
@ -1,9 +1,14 @@
|
||||
package com.genymobile.scrcpy;
|
||||
|
||||
import com.genymobile.scrcpy.wrappers.ServiceManager;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.AttributionSource;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.ContextWrapper;
|
||||
import android.content.IContentProvider;
|
||||
import android.os.Binder;
|
||||
import android.os.Process;
|
||||
|
||||
public final class FakeContext extends ContextWrapper {
|
||||
@ -17,6 +22,38 @@ public final class FakeContext extends ContextWrapper {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
private final ContentResolver contentResolver = new ContentResolver(this) {
|
||||
@SuppressWarnings({"unused", "ProtectedMemberInFinalClass"})
|
||||
// @Override (but super-class method not visible)
|
||||
protected IContentProvider acquireProvider(Context c, String name) {
|
||||
return ServiceManager.getActivityManager().getContentProviderExternal(name, new Binder());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
// @Override (but super-class method not visible)
|
||||
public boolean releaseProvider(IContentProvider icp) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unused", "ProtectedMemberInFinalClass"})
|
||||
// @Override (but super-class method not visible)
|
||||
protected IContentProvider acquireUnstableProvider(Context c, String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
// @Override (but super-class method not visible)
|
||||
public boolean releaseUnstableProvider(IContentProvider icp) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
// @Override (but super-class method not visible)
|
||||
public void unstableProviderDied(IContentProvider icp) {
|
||||
// ignore
|
||||
}
|
||||
};
|
||||
|
||||
private FakeContext() {
|
||||
super(Workarounds.getSystemContext());
|
||||
}
|
||||
@ -49,4 +86,9 @@ public final class FakeContext extends ContextWrapper {
|
||||
public Context getApplicationContext() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContentResolver getContentResolver() {
|
||||
return contentResolver;
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import com.genymobile.scrcpy.util.Ln;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.IContentProvider;
|
||||
import android.content.Intent;
|
||||
import android.os.Binder;
|
||||
import android.os.Bundle;
|
||||
@ -64,7 +65,7 @@ public final class ActivityManager {
|
||||
}
|
||||
|
||||
@TargetApi(AndroidVersions.API_29_ANDROID_10)
|
||||
private ContentProvider getContentProviderExternal(String name, IBinder token) {
|
||||
public IContentProvider getContentProviderExternal(String name, IBinder token) {
|
||||
try {
|
||||
Method method = getGetContentProviderExternalMethod();
|
||||
Object[] args;
|
||||
@ -83,11 +84,7 @@ public final class ActivityManager {
|
||||
// IContentProvider provider = providerHolder.provider;
|
||||
Field providerField = providerHolder.getClass().getDeclaredField("provider");
|
||||
providerField.setAccessible(true);
|
||||
Object provider = providerField.get(providerHolder);
|
||||
if (provider == null) {
|
||||
return null;
|
||||
}
|
||||
return new ContentProvider(this, provider, name, token);
|
||||
return (IContentProvider) providerField.get(providerHolder);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
Ln.e("Could not invoke method", e);
|
||||
return null;
|
||||
@ -104,7 +101,12 @@ public final class ActivityManager {
|
||||
}
|
||||
|
||||
public ContentProvider createSettingsProvider() {
|
||||
return getContentProviderExternal("settings", new Binder());
|
||||
IBinder token = new Binder();
|
||||
IContentProvider provider = getContentProviderExternal("settings", token);
|
||||
if (provider == null) {
|
||||
return null;
|
||||
}
|
||||
return new ContentProvider(this, provider, "settings", token);
|
||||
}
|
||||
|
||||
private Method getStartActivityAsUserMethod() throws NoSuchMethodException, ClassNotFoundException {
|
||||
|
Loading…
x
Reference in New Issue
Block a user