Skip to content

Commit

Permalink
Support IME in Freeform
Browse files Browse the repository at this point in the history
  • Loading branch information
sunshine0523 committed Sep 8, 2023
1 parent a50553c commit 49bd2d6
Show file tree
Hide file tree
Showing 24 changed files with 211 additions and 39 deletions.
6 changes: 5 additions & 1 deletion app/src/main/java/com/sunshine/freeform/MiFreeform.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.sunshine.freeform

import android.app.Application
import android.os.Build
import androidx.annotation.RequiresApi
import org.lsposed.hiddenapibypass.HiddenApiBypass

class MiFreeform: Application() {
Expand All @@ -15,7 +17,9 @@ class MiFreeform: Application() {
const val CONFIG = "config"

init {
HiddenApiBypass.addHiddenApiExemptions("")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
HiddenApiBypass.addHiddenApiExemptions("")
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package com.sunshine.freeform

import android.content.ComponentName
import android.os.Build
import android.os.IBinder
import android.os.ServiceManager
import android.util.Log
import androidx.annotation.RequiresApi
import com.google.gson.Gson
import com.sunshine.freeform.ui.main.RemoteSettings
import io.sunshine0523.freeform.IMiFreeformUIService
Expand All @@ -14,15 +17,27 @@ object MiFreeformServiceManager {
private val gson = Gson()

fun init() {
try {
val serviceManager = Class.forName("android.os.ServiceManager")
val r = HiddenApiBypass.invoke(serviceManager, null, "getService", "mi_freeform") as IBinder
Log.i(TAG, "mfs $r")
iMiFreeformService = IMiFreeformUIService.Stub.asInterface(r)
iMiFreeformService?.ping()
} catch (e: Exception) {
Log.e(TAG, "$e")
e.printStackTrace()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
try {
val serviceManager = Class.forName("android.os.ServiceManager")
val r = HiddenApiBypass.invoke(serviceManager, null, "getService", "mi_freeform") as IBinder
Log.i(TAG, "mfs $r")
iMiFreeformService = IMiFreeformUIService.Stub.asInterface(r)
iMiFreeformService?.ping()
} catch (e: Exception) {
Log.e(TAG, "$e")
e.printStackTrace()
}
} else {
try {
val r = ServiceManager.getService("mi_freeform")
Log.i(TAG, "mfs $r")
iMiFreeformService = IMiFreeformUIService.Stub.asInterface(r)
iMiFreeformService?.ping()
} catch (e: Exception) {
Log.e(TAG, "$e")
e.printStackTrace()
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ class MainViewModel(application: Application) : AndroidViewModel(application) {
private val remoteSetting = Gson().fromJson(MiFreeformServiceManager.getSetting(), RemoteSettings::class.java) ?: RemoteSettings()
private val _enableSideBar = MutableLiveData<Boolean>()
val enableSideBar: LiveData<Boolean> get() = _enableSideBar
private val _showImeInFreeform = MutableLiveData<Boolean>()
val showImeInFreeform: LiveData<Boolean> get() = _showImeInFreeform
private val _freeformWidth = MutableLiveData<Int>()
val freeformWidth: LiveData<Int> get() = _freeformWidth
private val _freeformHeight = MutableLiveData<Int>()
Expand All @@ -45,6 +47,7 @@ class MainViewModel(application: Application) : AndroidViewModel(application) {

init {
_enableSideBar.postValue(remoteSetting.enableSideBar)
_showImeInFreeform.postValue(remoteSetting.showImeInFreeform)
_freeformWidth.postValue(sp.getInt("freeform_width", (screenWidth * 0.8).roundToInt()))
_freeformHeight.postValue(sp.getInt("freeform_height", (screenHeight * 0.5).roundToInt()))
_freeformDensityDpi.postValue(sp.getInt("freeform_dpi", screenDensityDpi))
Expand All @@ -58,6 +61,12 @@ class MainViewModel(application: Application) : AndroidViewModel(application) {
MiFreeformServiceManager.setSetting(remoteSetting)
}

fun saveShowImeInFreeform(showImeInFreeform: Boolean) {
_showImeInFreeform.postValue(showImeInFreeform)
remoteSetting.showImeInFreeform = showImeInFreeform
MiFreeformServiceManager.setSetting(remoteSetting)
}

fun setFreeformWidth(width: Int) {
setIntSp(width, "freeform_width")
_freeformWidth.postValue(width)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ import androidx.annotation.Keep

@Keep
data class RemoteSettings(
var enableSideBar: Boolean = false
var enableSideBar: Boolean = false,
var showImeInFreeform: Boolean = false
)
11 changes: 11 additions & 0 deletions app/src/main/java/com/sunshine/freeform/ui/main/SettingView.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.sunshine.freeform.ui.main

import android.os.Build
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
Expand Down Expand Up @@ -39,6 +40,7 @@ import kotlin.math.roundToInt
@Composable
fun SettingWidget(mainViewModel: MainViewModel) {
val enableSideBar by mainViewModel.enableSideBar.observeAsState(false)
val showImeInFreeform by mainViewModel.showImeInFreeform.observeAsState(false)
val freeformWidth by mainViewModel.freeformWidth.observeAsState((mainViewModel.screenWidth * 0.8).roundToInt())
val freeformHeight by mainViewModel.freeformHeight.observeAsState((mainViewModel.screenHeight * 0.5).roundToInt())
val freeformDpi by mainViewModel.freeformDensityDpi.observeAsState(mainViewModel.screenDensityDpi)
Expand Down Expand Up @@ -107,6 +109,15 @@ fun SettingWidget(mainViewModel: MainViewModel) {
) {
mainViewModel.setFreeformDpi(it.roundToInt())
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
SettingSwitchOption(
stringResource(id = R.string.show_ime_in_freeform),
stringResource(id = R.string.show_ime_in_freeform_message),
showImeInFreeform
) {
mainViewModel.saveShowImeInFreeform(it)
}
}
}
}

Expand Down
2 changes: 2 additions & 0 deletions app/src/main/res/values-zh-rCN/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,6 @@
<string name="title_activity_freeform_app">选择小窗应用</string>
<string name="setting">设置</string>
<string name="log">日志</string>
<string name="show_ime_in_freeform">在小窗中展示输入法</string>
<string name="show_ime_in_freeform_message">在小窗中展示输入法,仅支持Android 12+</string>
</resources>
2 changes: 2 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,6 @@

<!--FreeformAppActivity-->
<string name="title_activity_freeform_app">Choose Freeform App</string>
<string name="show_ime_in_freeform">Show IME in Freeform</string>
<string name="show_ime_in_freeform_message">Show IME in Freeform. Only support Android 12+</string>
</resources>
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ plugins {
}

val androidTargetSdkVersion by extra(34)
val androidMinSdkVersion by extra(29)
val androidMinSdkVersion by extra(27)
val androidBuildToolsVersion by extra("34.0.0-rc3")
val androidCompileSdkVersion by extra(34)
val androidSourceCompatibility by extra(JavaVersion.VERSION_17)
Expand Down
1 change: 1 addition & 0 deletions freeform-server/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ dependencies {
implementation(libs.gson)
implementation(projects.service)
compileOnly(projects.hiddenApi)
compileOnly(libs.core.ktx)
}

zygote {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
ui_print "- Copy Mi-Freeform service dex to /data/system/mi_freeform"

mkdir "/data/system/mi_freeform"
chmod 777 "/data/system/mi_freeform"
cp "$MODPATH/classes.dex" "/data/system/mi_freeform/freeform.dex"
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ public DisplayDeviceInfo getDisplayDeviceInfoLocked() {
mInfo.yDpi = mDensityDpi;
mInfo.presentationDeadlineNanos = mDisplayPresentationDeadlineNanos +
1000000000L / (int) mRefreshRate; // display's deadline + 1 frame
mInfo.flags = DisplayDeviceInfo.FLAG_PRESENTATION;
//mInfo.flags = DisplayDeviceInfo.FLAG_PRESENTATION;
if (mFlags.mSecure) {
mInfo.flags |= DisplayDeviceInfo.FLAG_SECURE;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ private static void instanceMFService(Binder service) throws NoSuchFieldExceptio
miFreeformDisplayAdapterObj = mfdaClass.getConstructors()[0].newInstance(mSyncRoot, mContext, mHandler, mDisplayDeviceRepo, mLogicalDisplayMapper, mUiHandler);
mfdaClass.getMethod("registerLocked").invoke(miFreeformDisplayAdapterObj);
}
// for Android Q,R
// for Android O,P,Q,R
else {
Field mListenerField = dmsClass.getDeclaredField("mDisplayAdapterListener");
Field mLogicalDisplaysField = dmsClass.getDeclaredField("mLogicalDisplays");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@

import io.sunshine0523.freeform.IMiFreeformDisplayCallback;
import io.sunshine0523.freeform.IMiFreeformUIService;
import io.sunshine0523.freeform.ui.freeform.FreeformWindow;
import io.sunshine0523.freeform.ui.freeform.FreeformWindowManager;
import io.sunshine0523.freeform.util.DataChangeListener;
import io.sunshine0523.freeform.util.DataHelper;
import io.sunshine0523.freeform.util.MLog;
import io.sunshine0523.freeform.util.Settings;
Expand Down Expand Up @@ -110,7 +112,10 @@ public String getSettings() {

@Override
public void setSettings(String settings) {
DataHelper.INSTANCE.saveSettings(settings, this.sideBarService);
DataHelper.INSTANCE.saveSettings(settings, () -> {
sideBarService.onChanged();
FreeformWindowManager.settings = DataHelper.INSTANCE.getSettings();
});
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package io.sunshine0523.freeform.service;

import android.app.IActivityManager;
import android.app.IActivityTaskManager;
import android.os.Build;
import android.os.ServiceManager;
import android.util.Log;
import android.view.IWindowManager;

import com.android.internal.statusbar.IStatusBarService;
import com.android.server.am.ActivityManagerService;
import com.android.server.input.InputManagerService;

import io.sunshine0523.freeform.util.MLog;
Expand All @@ -16,17 +16,25 @@ public class SystemServiceHolder {
private static final String TAG = "Mi-Freeform/SystemServiceHolder";

static InputManagerService inputManagerService;
//For O,P
public static IActivityManager activityManager;
//For Q,R,S,T
public static IActivityTaskManager activityTaskManager;
public static IWindowManager windowManager;
public static IStatusBarService statusBarService;

static void init(ServiceCallback callback) {
new Thread(() -> {
waitSystemService("activity_task");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
waitSystemService("activity_task");
activityTaskManager = IActivityTaskManager.Stub.asInterface(ServiceManager.getService("activity_task"));
} else {
waitSystemService("activity");
activityManager = IActivityManager.Stub.asInterface(ServiceManager.getService("activity"));
}
waitSystemService("input");
waitSystemService("window");
waitSystemService("statusbar");
activityTaskManager = IActivityTaskManager.Stub.asInterface(ServiceManager.getService("activity_task"));
inputManagerService = (InputManagerService) ServiceManager.getService("input");
windowManager = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
statusBarService = IStatusBarService.Stub.asInterface(ServiceManager.getService("statusbar"));
Expand All @@ -35,8 +43,9 @@ static void init(ServiceCallback callback) {
}

public static void waitSystemService(String name) {
int count = 20;
try {
while (null == ServiceManager.getService(name)) {
while (count-- > 0 && null == ServiceManager.getService(name)) {
Thread.sleep(1000);
MLog.i(TAG, name + " not start, wait 1s");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import android.os.Build
import android.util.Log
import android.view.Display
import android.window.TaskSnapshot
import androidx.annotation.RequiresApi
import io.sunshine0523.freeform.util.MLog
import kotlin.math.max
import kotlin.math.min
Expand Down Expand Up @@ -58,6 +59,10 @@ class FreeformTaskStackListener(

}

override fun onActivityLaunchOnSecondaryDisplayFailed() {

}

override fun onActivityLaunchOnSecondaryDisplayFailed(
taskInfo: ActivityManager.RunningTaskInfo?,
requestedDisplayId: Int
Expand All @@ -80,6 +85,10 @@ class FreeformTaskStackListener(
Log.i(TAG, "onTaskRemoved $taskId")
}

override fun onTaskMovedToFront(taskId: Int) {
Log.i(TAG, "onTaskMovedToFront $taskId")
}

override fun onTaskMovedToFront(taskInfo: ActivityManager.RunningTaskInfo) {
Log.i(TAG, "onTaskMovedToFront $taskInfo")
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
Expand All @@ -88,6 +97,10 @@ class FreeformTaskStackListener(
// }
}

override fun onTaskDescriptionChanged(taskId: Int, td: ActivityManager.TaskDescription?) {
Log.i(TAG, "onTaskDescriptionChanged $taskId $td")
}

override fun onTaskDescriptionChanged(taskInfo: ActivityManager.RunningTaskInfo?) {
Log.i(TAG, "onTaskDescriptionChanged $taskInfo")
// Use this not onTaskMovedToFront because task maybe changed
Expand Down Expand Up @@ -121,25 +134,37 @@ class FreeformTaskStackListener(
Log.i(TAG, "onActivityRequestedOrientationChanged $taskId $requestedOrientation")
}

override fun onTaskRemovalStarted(taskId: Int) {
Log.i(TAG, "onTaskRemovalStarted")
if (this.taskId == taskId) {
window.destroy(false)
}
}

@RequiresApi(Build.VERSION_CODES.Q)
override fun onTaskRemovalStarted(taskInfo: ActivityManager.RunningTaskInfo?) {
Log.i(TAG, "onTaskRemovalStarted")
if (this.taskId == taskInfo?.taskId) {
window.destroy(false)
}
}

override fun onTaskProfileLocked(taskInfo: ActivityManager.RunningTaskInfo?) {
override fun onTaskProfileLocked(taskId: Int, userId: Int) {

}

override fun onTaskSnapshotChanged(taskId: Int, snapshot: TaskSnapshot?) {
override fun onTaskProfileLocked(taskInfo: ActivityManager.RunningTaskInfo?) {

}

override fun onTaskSnapshotChanged(taskId: Int, snapshot: ActivityManagerHidden.TaskSnapshot?) {

}

override fun onTaskSnapshotChanged(taskId: Int, snapshot: TaskSnapshot?) {

}

override fun onBackPressedOnTaskRoot(taskInfo: ActivityManager.RunningTaskInfo?) {

}
Expand Down
Loading

0 comments on commit 49bd2d6

Please sign in to comment.