/*
 * 强制锁定指定刷新率
 */
function lockRefreshRate(modeId) {
    realMode = modeId - 1;

    sf = android.os.ServiceManager.getService("SurfaceFlinger");

    data = android.os.Parcel.obtain();
    data.writeInterfaceToken("android.ui.ISurfaceComposer");
    data.writeInt(realMode);
    sf.transact(1035, data, null, 0);
}
// 重启需重新设置,个别系统锁屏后也会失效,自己测试。
// 改成自己想锁定的刷新率对应ID,不要乱填
lockRefreshRate(1);

#MVEL表达式 #Javascript
modes = (android.os.ServiceManager.getService("display").getDisplayInfo(android.view.Display.DEFAULT_DISPLAY)).supportedModes;
s = "";
for (i = 0; i < modes.length; i++) {
    m = modes[i];
    s += "id=" + m.getModeId() + ": " + m.getRefreshRate() + "Hz\n";
}
s.trim();
// 获取当前显示屏支持的刷新率以及对应ID

#MVEL表达式 #Javascript
/*
 * 显示刷新率开关控制函数
 *     0 = 关闭
 *     1 = 开启  
 *     2 = 查询当前状态(返回 true/false)
 *     3 = 切换(打开→关 / 关→开)
 */
function showRefreshRate(mode) {
    sf = android.os.ServiceManager.getService("SurfaceFlinger");

    function call(flag, needReply) {
        data = android.os.Parcel.obtain();
        reply = needReply ? android.os.Parcel.obtain() : null;
        data.writeInterfaceToken("android.ui.ISurfaceComposer");
        data.writeInt(flag);
        sf.transact(1034, data, reply, 0);
        return reply;
    }

    if (mode == 3) {
        current = call(2, true).readBoolean();
        call(current ? 0 : 1, false);
        return !current;
    }

    // mode: 0=关 1=开 2=查
    if (mode == 2) {
        return call(2, true).readBoolean();
    } else {
        call(mode, false);
        return mode == 1;
    }
}

// 切换显示屏刷新率显示开关
showRefreshRate(3);

#MVEL表达式 #Javascript
/*
// 媒体音量
audioManager.STREAM_MUSIC
// 通话音量
audioManager.STREAM_VOICE_CALL
// 铃声音量
audioManager.STREAM_RING
// 通知音量
audioManager.STREAM_NOTIFICATION
// 闹钟音量
audioManager.STREAM_ALARM
// 系统音量
audioManager.STREAM_SYSTEM
*/

#音量类型
audioManager = context.getSystemService("audio");
audio =android.os.ServiceManager.getService("audio");
function getVolumeInfo(context, streamType, targetVolume) {
    currentVolume = audio.getStreamVolume(streamType);
    maxVolume = audio.getStreamMaxVolume(streamType);
    return maxVolume;
}

getVolumeInfo(context, audioManager.STREAM_ALARM);
// 获取指定音量类型的上限

#MVEL表达式 #Javascript
audioManager = context.getSystemService("audio");
audio =android.os.ServiceManager.getService("audio");
function getVolumeInfo(context, streamType, targetVolume) {
    currentVolume = audio.getStreamVolume(streamType);
    newVolume = currentVolume + targetVolume;
    maxVolume = audio.getStreamMaxVolume(streamType);
    minVolume = 0;
    newVolume = Math.max(minVolume, Math.min(newVolume, maxVolume));
    audio.setStreamVolume(streamType, newVolume, 0, null);
    return newVolume;
}

getVolumeInfo(context, audioManager.STREAM_ALARM, 2);
// 调整闹钟音量(比如2 或 -2)
// 调节指定音量类型

#MVEL表达式 #Javascript
audioManager = context.getSystemService("audio");
function getVolumeInfo(context, streamType, targetVolume) {
     volume = android.os.ServiceManager.getService("audio").setStreamVolume(streamType, targetVolume, 0, null);
    return volume;
}

getVolumeInfo(context, audioManager.STREAM_ALARM, 7);
// 设置闹钟音量
// 设置指定音量类型

#MVEL表达式 #Javascript
audioManager = context.getSystemService("audio");
// 获取指定音量类型的音量值并返回
function getVolumeInfo(context, streamType) {
     volume = android.os.ServiceManager.getService("audio").getStreamVolume(streamType);
    return volume;
}

getVolumeInfo(context, audioManager.STREAM_RING);
// 获取当前铃声音量
// 获取指定音量类型当前音量

#MVEL表达式 #Javascript
next = android.os.ServiceManager.getService("alarm").getNextWakeFromIdleTime();

if (next >= 9000000000) {
    "当前没有任何会唤醒设备的闹钟";
} else {
    real = java.lang.System.currentTimeMillis() + next - android.os.SystemClock.elapsedRealtime();
    new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new java.util.Date(real));
}
// 获取下一次从Doze/空闲模式唤醒的时间

#MVEL表达式 #Javascript
Settings = android.provider.Settings;
Settings.Global.putString(context.getContentResolver(), 'auto_time', 0);
Settings.Global.putString(context.getContentResolver(), 'auto_time', 1);
// 设置恢复系统时间

#MVEL表达式 #Javascript
function createTimestamp(year, month, day, hour, minute, second) {
    Calendar = java.util.Calendar;
    cal = Calendar.getInstance();
    cal.set(year, month - 1, day, hour, minute, second);
    cal.set(Calendar.MILLISECOND, 0);
    return cal.getTimeInMillis();
}

// 示例为2023年12月25日 14点30分30秒
timestamp = createTimestamp(2023, 12, 25, 14, 30, 30);

android.os.ServiceManager.getService("alarm").setTime(timestamp); 
// 设置系统时间

#MVEL表达式 #Javascript
Intent = android.content.Intent;
UserHandle = android.os.UserHandle;
// ShortX自带的百度地图骑行导航无法正常使用,该接口可以
lat = 39.915119;
// lat - 纬度
lon = 116.403963;
// lon - 经度
coord_type = "bd09ll";
/*
坐标类型
bd09ll(百度经纬度坐标) //用百度坐标拾取器,可避免误差
bd09mc(百度墨卡托坐标)
gcj02(经国测局加密的坐标)
wgs84(gps获取的原始坐标)
*/
// 电动车导航
myIntent = Intent.parseUri('baidumap://map/bikenavi?destination=' + lat + ',' + lon + '&coord_type=' + coord_type + '&src=andr.baidu.openAPIdemo', 0);

myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// 指定用户启动
userHandle = UserHandle.of(0);

context.startActivityAsUser(myIntent, userHandle);
// 坐标拾取器 https://lbs.baidu.com/maptool/getpoint
// 指定用户百度地图 电动车导航

#MVEL表达式 #Javascript
Intent = android.content.Intent;
UserHandle = android.os.UserHandle;

lat = 39.915119;
// lat - 纬度
lon = 116.403963;
// lon - 经度
coord_type = "bd09ll";
/*
坐标类型
bd09ll(百度经纬度坐标) //用百度坐标拾取器,可避免误差
bd09mc(百度墨卡托坐标)
gcj02(经国测局加密的坐标)
wgs84(gps获取的原始坐标)
*/
// 步行导航
myIntent = Intent.parseUri('baidumap://map/walknavi?destination=' + lat + ',' + lon + '&coord_type=' + coord_type + '&src=andr.baidu.openAPIdemo', 0);

myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// 指定用户启动
userHandle = UserHandle.of(0);

context.startActivityAsUser(myIntent, userHandle);
// 坐标拾取器 https://lbs.baidu.com/maptool/getpoint
// 指定用户百度地图 步行导航

#MVEL表达式 #Javascript
Intent = android.content.Intent;
UserHandle = android.os.UserHandle;
// ShortX自带高德地图骑行导航无法细分自行车或电动车,该接口可以
lat = 39.909187;
// lat - 纬度
lon = 116.397463;
// lon - 经度
rideType = "bike";
// 骑行类型,elebike 为电动车,bike 或留空为自行车。

myIntent = Intent.parseUri('amapuri://openFeature?featureName=OnRideNavi&rideType=' + rideType + '&sourceApplication=null&lat=' + lat +'&lon=' + lon, 0);

myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// 指定用户启动
userHandle = UserHandle.of(0);

context.startActivityAsUser(myIntent, userHandle);
// 坐标拾取器 https://lbs.amap.com/tools/picker
// 指定用户高德地图 自行车导航

#MVEL表达式 #Javascript
Intent = android.content.Intent;
UserHandle = android.os.UserHandle;

lat = 39.909187;
// lat - 纬度
lon = 116.397463;
// lon - 经度

myIntent = Intent.parseUri('amapuri://openFeature?featureName=OnFootNavi&sourceApplication=null&lat=' + lat +'&lon=' + lon, 0);

myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// 指定用户启动
userHandle = UserHandle.of(0);

context.startActivityAsUser(myIntent, userHandle);

// 坐标拾取器 https://lbs.amap.com/tools/picker
// 指定用户高德地图 步行导航

#MVEL表达式 #Javascript
Intent = android.content.Intent;
ComponentName = android.content.ComponentName;

bgStreamIntent = new Intent();
bgStreamIntent.setComponent(new ComponentName("com.oplus.exsystemservice", "com.oplus.backgroundstream.RouteForegroundService"));
bgStreamIntent.setAction("oplus.intent.action.BACKGROUND_STREAM_SERVICE");

context.startService(bgStreamIntent);
// Color系统的听剧模式 | 后台挂机
// Color16 不可用

#MVEL表达式 #Javascript
android.os.ServiceManager.getService("lock_settings").getPassword();
// 获取 Color 系统的锁屏密码,
/* 
设置新密码后,需锁屏输入一次密码
Color16 不可用
*/

#MVEL表达式 #Javascript
/*
指定用户指定应用传感器管理
支持禁用、解除、查看,重置
*/
ServiceManager = android.os.ServiceManager;
ParcelFileDescriptor = android.os.ParcelFileDescriptor;

function runSensorCmd(args, userId) {

    svc = ServiceManager.getService("sensorservice");

    pin  = ParcelFileDescriptor.createPipe();
    pout = ParcelFileDescriptor.createPipe();
    perr = ParcelFileDescriptor.createPipe();

    pin[1].close();

    // 如果有指定用户,添加 --user 参数
    if (userId != undefined && userId != null) {
        args.push("--user");
        args.push(String(userId));
    }

    svc.shellCommand(
        pin[0].getFileDescriptor(),
        pout[1].getFileDescriptor(),
        perr[1].getFileDescriptor(),
        args,
        null,
        new android.os.ResultReceiver(null)
    );

    pout[1].close();
    perr[1].close();

    function read(p){
        s = new android.os.ParcelFileDescriptor.AutoCloseInputStream(p[0]);
        r = "";
        b = java.lang.reflect.Array.newInstance(java.lang.Byte.TYPE, 1024);
        n ="";
        while((n = s.read(b)) > 0){
            r += new java.lang.String(b, 0, n, "UTF-8");
        }
        return r;
    }

    result = read(pout) + read(perr);
    result = result.trim();

    if (args[0] == "get-uid-state") {
        if (result.includes("idle")) return true;
        if (result.includes("active")) return false;
        return false;

    }

    return result;
}

// 1) 禁用(设置为 idle,相当于限制传感器)
// runSensorCmd(["set-uid-state", "包名", "idle"], 0);

// 2) 恢复 active(取消限制)
// runSensorCmd(["set-uid-state", "com.liuzh.deviceinfo", "active"], 0);

// 3) 查看状态
// true 已禁用 false 未禁用
runSensorCmd(["get-uid-state", "com.liuzh.deviceinfo"], 0);

// 4) 恢复默认(清除 override)
// runSensorCmd(["reset-uid-state", "包名"], 0);

// 该接口不会禁用摄像头和麦克风,下载类似设备信息APP测试效果
// Android 11-16已测试成功,其他版本未知

#Javascript
context.getSystemService("sensor_privacy").suppressSensorPrivacyReminders(1, true, 0)
// 设置指定用户麦克风隐私状态提示禁用弹窗
/*
(int sensor, boolean suppress, int userId)
sensor:1=麦克风、2=摄像头
suppress:true=屏蔽弹窗
*/

#MVEL表达式 #Javascript
Back to Top