Skip to content

Commit

Permalink
Add workarounds for Honor devices
Browse files Browse the repository at this point in the history
Audio did not work on Honor devices.

To make it work, a system context must be set as a base context of
FakeContext (so that a PackageManager is available), and a current
ActivityThread must be initialized.

These workarounds must not be applied for all devices, because they
might cause other issues.

Fixes #4015 <#4015>
Refs #3085 <#3805>

Co-authored-by: Simon Chan <1330321+yume-chan@users.noreply.github.com>
  • Loading branch information
rom1v and yume-chan committed Jun 19, 2023
1 parent 48a00fb commit feb247f
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 10 deletions.
4 changes: 2 additions & 2 deletions server/src/main/java/com/genymobile/scrcpy/FakeContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

import android.annotation.TargetApi;
import android.content.AttributionSource;
import android.content.ContextWrapper;
import android.content.MutableContextWrapper;
import android.os.Build;
import android.os.Process;

public final class FakeContext extends ContextWrapper {
public final class FakeContext extends MutableContextWrapper {

public static final String PACKAGE_NAME = "com.android.shell";
public static final int ROOT_UID = 0; // Like android.os.Process.ROOT_UID, but before API 29
Expand Down
24 changes: 16 additions & 8 deletions server/src/main/java/com/genymobile/scrcpy/Server.java
Original file line number Diff line number Diff line change
Expand Up @@ -101,16 +101,24 @@ private static void scrcpy(Options options) throws IOException, ConfigurationExc

Workarounds.prepareMainLooper();

// Workarounds must be applied for Meizu phones:
// - <https://github.com/Genymobile/scrcpy/issues/240>
// - <https://github.com/Genymobile/scrcpy/issues/365>
// - <https://github.com/Genymobile/scrcpy/issues/2656>
//
// But only apply when strictly necessary, since workarounds can cause other issues:
// - <https://github.com/Genymobile/scrcpy/issues/940>
// - <https://github.com/Genymobile/scrcpy/issues/994>
if (Build.BRAND.equalsIgnoreCase("meizu")) {
// Workarounds must be applied for Meizu phones:
// - <https://github.com/Genymobile/scrcpy/issues/240>
// - <https://github.com/Genymobile/scrcpy/issues/365>
// - <https://github.com/Genymobile/scrcpy/issues/2656>
//
// But only apply when strictly necessary, since workarounds can cause other issues:
// - <https://github.com/Genymobile/scrcpy/issues/940>
// - <https://github.com/Genymobile/scrcpy/issues/994>
Workarounds.fillAppInfo();
} else if (Build.BRAND.equalsIgnoreCase("honor")) {
// Honor devices require in addition a system context as a base context of FakeContext:
// - <https://github.com/Genymobile/scrcpy/issues/4015>
// The system context must not be set for all devices, because it would cause other problems:
// - <https://github.com/Genymobile/scrcpy/issues/4015#issuecomment-1595382142>
// - <https://github.com/Genymobile/scrcpy/issues/3805#issuecomment-1596148031>
Workarounds.fillAppInfo();
Workarounds.fillBaseContext();
}

// Before Android 11, audio is not supported.
Expand Down
14 changes: 14 additions & 0 deletions server/src/main/java/com/genymobile/scrcpy/Workarounds.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import android.annotation.TargetApi;
import android.app.Application;
import android.content.AttributionSource;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.pm.ApplicationInfo;
import android.media.AudioAttributes;
Expand Down Expand Up @@ -105,6 +106,19 @@ public static void fillAppContext() {
}
}

public static void fillBaseContext() {
try {
fillActivityThread();

Method getSystemContextMethod = activityThreadClass.getDeclaredMethod("getSystemContext");
Context context = (Context) getSystemContextMethod.invoke(activityThread);
FakeContext.get().setBaseContext(context);
} catch (Throwable throwable) {
// this is a workaround, so failing is not an error
Ln.d("Could not fill base context: " + throwable.getMessage());
}
}

@TargetApi(Build.VERSION_CODES.R)
@SuppressLint("WrongConstant,MissingPermission,BlockedPrivateApi,SoonBlockedPrivateApi,DiscouragedPrivateApi")
public static AudioRecord createAudioRecord(int source, int sampleRate, int channelConfig, int channels, int channelMask, int encoding) {
Expand Down

0 comments on commit feb247f

Please sign in to comment.