Settings开发者模式添加OTG切换功能

框架

框架接口在frameworks/base/packages/SettingsLib当中

Settings开发者模式代码: packages/apps/Settings/src/com/android/settings/development/OtgPreferenceController.java

层级 职责 示例
SettingsLib (基类) 核心业务逻辑:读写系统节点、状态管理、UI更新 AbstractEnableAdbPreferenceController --- 读写 Settings.Global.ADB_ENABLED
Settings App (子类) UI层特有逻辑:弹窗、Fragment 引用等 AdbPreferenceController --- 弹出确认对话框
  • SettingsLib中创建 AbstractEnableOtgPreferenceController 来 作为接口管理
  • 在Settings APP中创建 OtgPreferenceController 起到呈上起下的作用

XML配置

  • 字符配置位置(找到的去Framework去查找):frameworks/base/packages/SettingsLib/res/values/strings.xml
xml 复制代码
<string name="enable_adb">USB debugging</string>
<!-- Setting checkbox summary for Whether to enable USB debugging support on the phone -->
<string name="enable_adb_summary">Debug mode when USB is connected</string>

<string name="enable_otg">OTG Mode</string>
<!-- Setting checkbox summary for Whether to enable otg debugging support on the phone -->
<string name="enable_otg_summary">OTG mode when OTG interface is connected</string>
  • UI所在位置在 Settings 当中 ,packages/apps/Settings/res/xml/development_settings.xml
xml 复制代码
<com.android.settingslib.RestrictedSwitchPreference
    android:key="enable_adb"
    android:title="@string/enable_adb"
    android:summary="@string/enable_adb_summary" />

<SwitchPreference
    android:key="enable_otg"
    android:title="@string/enable_otg"
    android:summary="@string/enable_otg_summary" />

Fragment加载

packages/apps/Settings/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java

  • 初始化过程中 框架会 自动遍历所有 Controller
java 复制代码
 controllers.add(new OtgPreferenceController(context));
  • Settingsextend AbstractEnableAdbPreferenceController

  • OtgPreferenceController extend AbstractEnableOtgPreferenceController类 来调用 SettingsLib 方法

    package com.android.settings.development;
    import android.content.Context;
    import com.android.settings.core.PreferenceControllerMixin;
    import com.android.settingslib.development.AbstractEnableOtgPreferenceController;
    /**

    • Preference controller for the OTG mode switch in Developer Options.
    • Extends {@link AbstractEnableOtgPreferenceController} from SettingsLib which handles

    • all core logic: reading/writing the sysfs node at
    • {@code /sys/devices/platform/2602e000.syscon/2602e000.syscon:usb2-phy@0/otg_mode},
    • UI state updates, and developer-options-switch reset behavior.
    • No confirmation dialog is shown --- toggling takes effect immediately.

    */
    public class OtgPreferenceController extends AbstractEnableOtgPreferenceController implements
    PreferenceControllerMixin {

    复制代码
      public OtgPreferenceController(Context context) {
          super(context);
      }

    }

  • xml 如何 和 Java 通过 Key 实现 绑定

java 复制代码
public abstract class AbstractEnableOtgPreferenceController extends
        DeveloperOptionsPreferenceController {

    private static final String TAG = "EnableOtgPrefCtrl";
    private static final String KEY_ENABLE_OTG = "enable_otg";

    /** Sysfs node path for OTG mode control on RK3576 platform. */
    private static final String OTG_MODE_SYSFS_PATH =
            "/sys/devices/platform/2602e000.syscon/2602e000.syscon:usb2-phy@0/otg_mode";
    private static final String OTG_PORT = "persist.sys.otg.mode";

    /** Value written to sysfs to enable OTG mode. */
    private static final String OTG_MODE_VALUE_ON = "otg";
    /** Value written to sysfs to disable OTG (i.e., switch to HOST mode). */
    private static final String OTG_MODE_VALUE_OFF = "host";

    public AbstractEnableOtgPreferenceController(Context context) {
        super(context);
    }
	// 告诉框架,此类事哪个XML元素的Controller,返回值与xml中定义的key完全一致。
    @Override
    public String getPreferenceKey() {
        return KEY_ENABLE_OTG;
    }

    @Override
    public void displayPreference(PreferenceScreen screen) {
        super.displayPreference(screen);
        if (isAvailable()) {
            mPreference = (TwoStatePreference) screen.findPreference(KEY_ENABLE_OTG);
        }
    }
	// true是否可见
    @Override
    public boolean isAvailable() {
        return true;
    }

    @Override
    public void updateState(Preference preference) {
        boolean otgEnabled = isOtgEnabled();
        ((TwoStatePreference) preference).setChecked(otgEnabled);
    }

    @Override
    public boolean handlePreferenceTreeClick(Preference preference) {
        if (!KEY_ENABLE_OTG.equals(preference.getKey())) {
            return false;
        }
        boolean isChecked = ((TwoStatePreference) preference).isChecked();
        writeOtgSetting(isChecked);
        return true;
    }
    /**
     * Write OTG mode to the sysfs node.
     *
     * @param enable true for OTG mode, false for HOST mode.
     */
    protected void writeOtgSetting(boolean enable) {
        String value = enable ? OTG_MODE_VALUE_ON : OTG_MODE_VALUE_OFF;
        SystemProperties.set(OTG_PORT, value);
        writeSysfsNode(OTG_MODE_SYSFS_PATH, value);
        Log.d(TAG, "writeOtgSetting: enable=" + enable + ", wrote '" + value + "'");
    }

    /**
     * Read current OTG mode from the sysfs node.
     *
     * @return true if currently in OTG mode, false if in HOST mode.
     */
    protected boolean isOtgEnabled() {
        // String currentValue = readSysfsNode(OTG_MODE_SYSFS_PATH);
        String currentValue = SystemProperties.get(OTG_PORT,OTG_MODE_VALUE_ON);
        boolean enabled = OTG_MODE_VALUE_ON.equalsIgnoreCase(currentValue);
        Log.d(TAG, "isOtgEnabled: value='" + currentValue + "', enabled=" + enabled);
        return enabled;
    }

    /**
     * Called when Developer Options master switch is turned OFF.
     * Resets OTG back to HOST mode.
     */
    @Override
    protected void onDeveloperOptionsSwitchDisabled() {
        super.onDeveloperOptionsSwitchDisabled();
        writeOtgSetting(false);
        if (mPreference != null) {
            ((TwoStatePreference) mPreference).setChecked(false);
        }
    }

    // ==================== Sysfs I/O Utilities ====================

    /**
     * Write a string value to a sysfs node.
     *
     * @param path  absolute path of the sysfs file.
     * @param value the string value to write.
     */
    private static void writeSysfsNode(String path, String value) {
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(path);
            fos.write(value.getBytes());
            fos.flush();
        } catch (IOException e) {
            Log.e(TAG, "Failed to write '" + value + "' to " + path, e);
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    Log.e(TAG, "Error closing " + path, e);
                }
            }
        }
    }

    /**
     * Read a string value from a sysfs node.
     *
     * @param path absolute path of the sysfs file.
     * @return the trimmed content of the file, or empty string on error.
     */
    private static String readSysfsNode(String path) {
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new FileReader(path));
            String line = reader.readLine();
            return (line != null) ? line.trim() : "";
        } catch (IOException e) {
            Log.e(TAG, "Failed to read from " + path, e);
            return "";
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    Log.e(TAG, "Error closing reader for " + path, e);
                }
            }
        }
    }
}
相关推荐
浩宇软件开发2 个月前
基于Android天气预报应用开发APP
android·java·android studio·android开发
Android出海4 个月前
Google Play“先试后买”功能曝光:解决买断制游戏试玩痛点
游戏·游戏开发·android开发·google play·app出海·游戏出海·android出海
~央千澈~10 个月前
老项目Android开发环境搭建的困境与解决之道-优雅草卓伊凡
gradle·android开发·安卓开发
~央千澈~1 年前
【03】完整开发腾讯云播放器SDK的UniApp官方UTS插件——优雅草上架插件市场-卓伊凡
android-studio·android开发·uts·uts原生插件
8931519601 年前
Android开发Glide做毛玻璃效果
android·glide·android开发·android教程·glide做毛玻璃效果
浩宇软件开发1 年前
Android开发,实现一个简约又好看的登录页
android·java·android studio·android开发
8931519601 年前
Android开发融云获取多个会话的总未读数
android·android开发·android教程·融云获取多个会话的总未读数·融云未读数
8931519601 年前
Android穿山甲banner广告穿插到项目的banner中
android·android开发·android教程·穿山甲banner广告加入项目
8931519601 年前
Android开发检查是否是各大厂商手机的工具类
android·android开发·android教程·android检查手机厂商