diff --git a/server/src/main/java/com/genymobile/scrcpy/Command.java b/server/src/main/java/com/genymobile/scrcpy/Command.java new file mode 100644 index 00000000..0ef976a6 --- /dev/null +++ b/server/src/main/java/com/genymobile/scrcpy/Command.java @@ -0,0 +1,33 @@ +package com.genymobile.scrcpy; + +import java.io.IOException; +import java.util.Arrays; +import java.util.Scanner; + +public final class Command { + private Command() { + // not instantiable + } + + public static void exec(String... cmd) throws IOException, InterruptedException { + Process process = Runtime.getRuntime().exec(cmd); + int exitCode = process.waitFor(); + if (exitCode != 0) { + throw new IOException("Command " + Arrays.toString(cmd) + " returned with value " + exitCode); + } + } + + public static String execReadLine(String... cmd) throws IOException, InterruptedException { + String result = null; + Process process = Runtime.getRuntime().exec(cmd); + Scanner scanner = new Scanner(process.getInputStream()); + if (scanner.hasNextLine()) { + result = scanner.nextLine(); + } + int exitCode = process.waitFor(); + if (exitCode != 0) { + throw new IOException("Command " + Arrays.toString(cmd) + " returned with value " + exitCode); + } + return result; + } +} diff --git a/server/src/main/java/com/genymobile/scrcpy/Settings.java b/server/src/main/java/com/genymobile/scrcpy/Settings.java index 83b63477..cb15ebb4 100644 --- a/server/src/main/java/com/genymobile/scrcpy/Settings.java +++ b/server/src/main/java/com/genymobile/scrcpy/Settings.java @@ -3,6 +3,10 @@ package com.genymobile.scrcpy; import com.genymobile.scrcpy.wrappers.ContentProvider; import com.genymobile.scrcpy.wrappers.ServiceManager; +import android.os.Build; + +import java.io.IOException; + public class Settings { public static final String TABLE_SYSTEM = ContentProvider.TABLE_SYSTEM; @@ -15,25 +19,66 @@ public class Settings { this.serviceManager = serviceManager; } - public String getValue(String table, String key) throws SettingsException { - try (ContentProvider provider = serviceManager.getActivityManager().createSettingsProvider()) { - return provider.getValue(table, key); + private static void execSettingsPut(String table, String key, String value) throws SettingsException { + try { + Command.exec("settings", "put", table, key, value); + } catch (IOException | InterruptedException e) { + throw new SettingsException("put", table, key, value, e); } } + private static String execSettingsGet(String table, String key) throws SettingsException { + try { + return Command.execReadLine("settings", "get", table, key); + } catch (IOException | InterruptedException e) { + throw new SettingsException("get", table, key, null, e); + } + } + + public String getValue(String table, String key) throws SettingsException { + if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) { + // on Android >= 12, it always fails: + try (ContentProvider provider = serviceManager.getActivityManager().createSettingsProvider()) { + return provider.getValue(table, key); + } catch (SettingsException e) { + Ln.w("Could not get settings value via ContentProvider, fallback to settings process", e); + } + } + + return execSettingsGet(table, key); + } + public void putValue(String table, String key, String value) throws SettingsException { - try (ContentProvider provider = serviceManager.getActivityManager().createSettingsProvider()) { - provider.putValue(table, key, value); + if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) { + // on Android >= 12, it always fails: + try (ContentProvider provider = serviceManager.getActivityManager().createSettingsProvider()) { + provider.putValue(table, key, value); + } catch (SettingsException e) { + Ln.w("Could not put settings value via ContentProvider, fallback to settings process", e); + } } + + execSettingsPut(table, key, value); } public String getAndPutValue(String table, String key, String value) throws SettingsException { - try (ContentProvider provider = serviceManager.getActivityManager().createSettingsProvider()) { - String oldValue = provider.getValue(table, key); - if (!value.equals(oldValue)) { - provider.putValue(table, key, value); + if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) { + // on Android >= 12, it always fails: + try (ContentProvider provider = serviceManager.getActivityManager().createSettingsProvider()) { + String oldValue = provider.getValue(table, key); + if (!value.equals(oldValue)) { + provider.putValue(table, key, value); + } + return oldValue; + } catch (SettingsException e) { + Ln.w("Could not get and put settings value via ContentProvider, fallback to settings process", e); } - return oldValue; } + + String oldValue = getValue(table, key); + if (!value.equals(oldValue)) { + putValue(table, key, value); + } + return oldValue; } }