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
|
android/content/IOnPrimaryClipChangedListener.aidl
|
||||||
"$BUILD_TOOLS_DIR/aidl" -o"$GEN_DIR" -I. android/view/IDisplayFoldListener.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=( \
|
SRC=( \
|
||||||
com/genymobile/scrcpy/*.java \
|
com/genymobile/scrcpy/*.java \
|
||||||
com/genymobile/scrcpy/audio/*.java \
|
com/genymobile/scrcpy/audio/*.java \
|
||||||
@ -72,6 +77,7 @@ javac -encoding UTF-8 -bootclasspath "$ANDROID_JAR" \
|
|||||||
-cp "$LAMBDA_JAR:$GEN_DIR" \
|
-cp "$LAMBDA_JAR:$GEN_DIR" \
|
||||||
-d "$CLASSES_DIR" \
|
-d "$CLASSES_DIR" \
|
||||||
-source 1.8 -target 1.8 \
|
-source 1.8 -target 1.8 \
|
||||||
|
${FAKE_SRC[@]} \
|
||||||
${SRC[@]}
|
${SRC[@]}
|
||||||
|
|
||||||
echo "Dexing..."
|
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;
|
package com.genymobile.scrcpy;
|
||||||
|
|
||||||
|
import com.genymobile.scrcpy.wrappers.ServiceManager;
|
||||||
|
|
||||||
import android.annotation.TargetApi;
|
import android.annotation.TargetApi;
|
||||||
import android.content.AttributionSource;
|
import android.content.AttributionSource;
|
||||||
|
import android.content.ContentResolver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.ContextWrapper;
|
import android.content.ContextWrapper;
|
||||||
|
import android.content.IContentProvider;
|
||||||
|
import android.os.Binder;
|
||||||
import android.os.Process;
|
import android.os.Process;
|
||||||
|
|
||||||
public final class FakeContext extends ContextWrapper {
|
public final class FakeContext extends ContextWrapper {
|
||||||
@ -17,6 +22,38 @@ public final class FakeContext extends ContextWrapper {
|
|||||||
return INSTANCE;
|
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() {
|
private FakeContext() {
|
||||||
super(Workarounds.getSystemContext());
|
super(Workarounds.getSystemContext());
|
||||||
}
|
}
|
||||||
@ -49,4 +86,9 @@ public final class FakeContext extends ContextWrapper {
|
|||||||
public Context getApplicationContext() {
|
public Context getApplicationContext() {
|
||||||
return this;
|
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.SuppressLint;
|
||||||
import android.annotation.TargetApi;
|
import android.annotation.TargetApi;
|
||||||
|
import android.content.IContentProvider;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
@ -64,7 +65,7 @@ public final class ActivityManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@TargetApi(AndroidVersions.API_29_ANDROID_10)
|
@TargetApi(AndroidVersions.API_29_ANDROID_10)
|
||||||
private ContentProvider getContentProviderExternal(String name, IBinder token) {
|
public IContentProvider getContentProviderExternal(String name, IBinder token) {
|
||||||
try {
|
try {
|
||||||
Method method = getGetContentProviderExternalMethod();
|
Method method = getGetContentProviderExternalMethod();
|
||||||
Object[] args;
|
Object[] args;
|
||||||
@ -83,11 +84,7 @@ public final class ActivityManager {
|
|||||||
// IContentProvider provider = providerHolder.provider;
|
// IContentProvider provider = providerHolder.provider;
|
||||||
Field providerField = providerHolder.getClass().getDeclaredField("provider");
|
Field providerField = providerHolder.getClass().getDeclaredField("provider");
|
||||||
providerField.setAccessible(true);
|
providerField.setAccessible(true);
|
||||||
Object provider = providerField.get(providerHolder);
|
return (IContentProvider) providerField.get(providerHolder);
|
||||||
if (provider == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return new ContentProvider(this, provider, name, token);
|
|
||||||
} catch (ReflectiveOperationException e) {
|
} catch (ReflectiveOperationException e) {
|
||||||
Ln.e("Could not invoke method", e);
|
Ln.e("Could not invoke method", e);
|
||||||
return null;
|
return null;
|
||||||
@ -104,7 +101,12 @@ public final class ActivityManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public ContentProvider createSettingsProvider() {
|
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 {
|
private Method getStartActivityAsUserMethod() throws NoSuchMethodException, ClassNotFoundException {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user