Browse Source

[New] Audio silencer: mute any sound that can be uniquely identified; resolves #108

[New][MIUI 12] Sticky floating windows: remember window state, position and dimensions
[New][MIUI 12] Allow any app to be pened in floating window
[Improved][Recent apps background blur] Compatibility with recents from MIUI Launcher
[Fixed][Expand QS action][MIUI 12] Expands control center too; resolves #137
[Fixed][Detailed network speed indicator] Android 7.1 compatibility
[Fixed][Custom lock screen actions] Android 7.1 compatibility
[Fixed][MIUI 12] Module's settings crash on beta ROMs; resolves #144
master v3.0.3
Mikanoshi 11 months ago
parent
commit
730a3aa17c
39 changed files with 1018 additions and 169 deletions
  1. +1
    -0
      .idea/runConfigurations.xml
  2. +11
    -1
      CHANGELOG_EN
  3. +11
    -1
      CHANGELOG_RU
  4. +2
    -2
      app/build.gradle
  5. +6
    -2
      app/src/main/java/name/mikanoshi/customiuizer/MainFragment.java
  6. +8
    -2
      app/src/main/java/name/mikanoshi/customiuizer/MainModule.java
  7. +1
    -1
      app/src/main/java/name/mikanoshi/customiuizer/PreferenceFragmentBase.java
  8. +3
    -2
      app/src/main/java/name/mikanoshi/customiuizer/SnoozedFragment.java
  9. +6
    -3
      app/src/main/java/name/mikanoshi/customiuizer/mods/Controls.java
  10. +18
    -1
      app/src/main/java/name/mikanoshi/customiuizer/mods/GlobalActions.java
  11. +39
    -0
      app/src/main/java/name/mikanoshi/customiuizer/mods/Launcher.java
  12. +269
    -54
      app/src/main/java/name/mikanoshi/customiuizer/mods/System.java
  13. +12
    -8
      app/src/main/java/name/mikanoshi/customiuizer/subs/BTList.java
  14. +5
    -0
      app/src/main/java/name/mikanoshi/customiuizer/subs/CategorySelector.java
  15. +2
    -2
      app/src/main/java/name/mikanoshi/customiuizer/subs/MultiAction.java
  16. +2
    -1
      app/src/main/java/name/mikanoshi/customiuizer/subs/SortableList.java
  17. +9
    -0
      app/src/main/java/name/mikanoshi/customiuizer/subs/System.java
  18. +251
    -0
      app/src/main/java/name/mikanoshi/customiuizer/subs/System_AudioSilencer.java
  19. +8
    -4
      app/src/main/java/name/mikanoshi/customiuizer/subs/WiFiList.java
  20. +2
    -2
      app/src/main/java/name/mikanoshi/customiuizer/utils/HelperReceiver.java
  21. +52
    -17
      app/src/main/java/name/mikanoshi/customiuizer/utils/Helpers.java
  22. +5
    -3
      app/src/main/java/name/mikanoshi/customiuizer/utils/ModSearchAdapter.java
  23. +2
    -1
      app/src/main/java/name/mikanoshi/customiuizer/utils/PreferenceAdapter.java
  24. +5
    -3
      app/src/main/java/name/mikanoshi/customiuizer/utils/SnoozedAdapter.java
  25. +78
    -0
      app/src/main/java/name/mikanoshi/customiuizer/utils/SoundData.java
  26. +2
    -1
      app/src/main/res/layout/pref_header.xml
  27. +0
    -22
      app/src/main/res/layout/pref_header11.xml
  28. +1
    -1
      app/src/main/res/layout/pref_item.xml
  29. +22
    -27
      app/src/main/res/layout/pref_item_detailed.xml
  30. +75
    -0
      app/src/main/res/layout/prefs_system_audiosilencer.xml
  31. +12
    -0
      app/src/main/res/values-es/strings.xml
  32. +1
    -1
      app/src/main/res/values-pt-rBR/strings.xml
  33. +17
    -2
      app/src/main/res/values-ru-rRU/strings.xml
  34. +27
    -1
      app/src/main/res/values-zh-rCN/strings.xml
  35. +16
    -1
      app/src/main/res/values/strings.xml
  36. +2
    -2
      app/src/main/res/xml/prefs_launcher.xml
  37. +31
    -0
      app/src/main/res/xml/prefs_system.xml
  38. +3
    -0
      app/src/main/res/xml/prefs_system_cat.xml
  39. +1
    -1
      last_build

+ 1
- 0
.idea/runConfigurations.xml View File

@ -3,6 +3,7 @@
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="com.android.tools.idea.compose.preview.runconfiguration.ComposePreviewRunConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />


+ 11
- 1
CHANGELOG_EN View File

@ -1,10 +1,20 @@
3.0.3
[New] Audio silencer: mute any sound that can be uniquely identified
[New][MIUI 12] Sticky floating windows: remember window state, position and dimensions
[New][MIUI 12] Allow any app to be pened in floating window
[Improved][Recent apps background blur] Compatibility with recents from MIUI Launcher
[Fixed][Expand QS action][MIUI 12] Expands control center too
[Fixed][Detailed network speed indicator] Android 7.1 compatibility
[Fixed][Custom lock screen actions] Android 7.1 compatibility
[Fixed][MIUI 12] Module's settings crash on beta ROMs
3.0.2
[New] Disable media stream muting in Do not disturb mode
[New] Toggle DND instead of Silent mode from collapsed volume dialog
[New] Volume dialog autohide delay
[New] Google Keyboard's bottom padding
[New][MIUI 12] Allow floating window to be opened from any notification that has an appropriate click action defined
[Improved][Compact notifications][MIUI12] Increased height of action buttons
[Improved][Compact notifications][MIUI 12] Increased height of action buttons
[Fixed][Display next alarm on lock screen] Compatibility with super wallpaper clock style
[Fixed][Custom lock screen actions] Compatibility with some ancient Android versions
[Fixed][Popup notification swipe down] Ignore notifications with floating windows


+ 11
- 1
CHANGELOG_RU View File

@ -1,10 +1,20 @@
3.0.3
[Новое] Аудио глушитель: позволяет заглушить любой уникально опознаваемый звук
[Новое][MIUI 12] Перманентные плавающие окна: запоминание состояния, позиции и размеров
[Новое][MIUI 12] Разрешить открывать любое приложение в плавающем окне
[Улучшено][Размытие фона списка последних приложений] Совместимость со списком из Рабочего стола MIUI
[Исправлено][Действие открытия Быстрых Настроек][MIUI 12] Также открывать центр управления
[Исправлено][Подробный индикатор скорости соединения] Совместимость с Android 7.1
[Исправлено][Пользовательские действия на локскрине] Совместимость с Android 7.1
[Исправлено][MIUI 12] Вылет настроек модуля на бета прошивках
3.0.2
[Новое] Отключить заглушение музыки в режиме Не беспокоить
[Новое] Переключение режима Не беспокоить вместо Бесшумного режима из свёрнутого диалога громкости
[Новое] Время перед автоскрытием диалога громкости
[Новое] Нижний отступ в Google Клавиатуре
[Новое][MIUI 12] Разрешить плавающее окно по свайпу вниз, если у уведомления задано подходящее действие на нажатие
[Улучшено][Компактные уведомления][MIUI12] Увеличена высота кнопок действий
[Улучшено][Компактные уведомления][MIUI 12] Увеличена высота кнопок действий
[Исправлено][Показ будильника на локскрине] Совместимость со стилем часов от супер обоев
[Исправлено][Пользовательские действия на локскрине] Совместимость с некоторыми древними версиями Андроида
[Исправлено][Свайп вниз по всплывающим уведомлениям] Игнорировать уведомления с плавающими окнами


+ 2
- 2
app/build.gradle View File

@ -22,8 +22,8 @@ android {
minSdkVersion 24
//noinspection ExpiredTargetSdkVersion
targetSdkVersion 27
versionCode 56
versionName "3.0.2"
versionCode 57
versionName "3.0.3"
signingConfig signingConfigs.dev
}
buildTypes {


+ 6
- 2
app/src/main/java/name/mikanoshi/customiuizer/MainFragment.java View File

@ -353,7 +353,8 @@ public class MainFragment extends PreferenceFragmentBase {
public boolean onTouch(View v, MotionEvent event) {
if (actionMode != null && isSearchFocused) {
isSearchFocused = false;
hideKeyboard();
Handler handler = new Handler(v.getContext().getMainLooper());
handler.postDelayed(MainFragment.this::hideKeyboard, getResources().getInteger(android.R.integer.config_shortAnimTime));
}
return false;
}
@ -411,7 +412,10 @@ public class MainFragment extends PreferenceFragmentBase {
if (warning != null)
if (Helpers.areXposedBlacklistsEnabled()) {
warning.setTitle(R.string.warning);
warning.setSummary(R.string.warning_blacklist);
if (act.getApplicationContext().getApplicationInfo().targetSdkVersion > 27)
warning.setSummary(getString(R.string.warning_blacklist) + "\n" + getString(R.string.warning_blacklist_sdk));
else
warning.setSummary(R.string.warning_blacklist);
warning.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {


+ 8
- 2
app/src/main/java/name/mikanoshi/customiuizer/MainModule.java View File

@ -45,6 +45,8 @@ public class MainModule implements IXposedHookZygoteInit, IXposedHookLoadPackage
mPrefs.putAll(pref.getAll());
}
if (!startParam.startsSystemServer) return;
resHooks = new ResourceHooks();
GlobalActions.miuizerSettingsResInit();
@ -94,12 +96,13 @@ public class MainModule implements IXposedHookZygoteInit, IXposedHookLoadPackage
if (mPrefs.getBoolean("system_hidelowbatwarn")) System.NoLowBatteryWarningHook();
if (mPrefs.getBoolean("system_screenshot_overlay")) System.TempHideOverlayHook();
if (mPrefs.getBoolean("system_nomediamute")) System.NoMediaMuteInDNDHook();
if (mPrefs.getBoolean("system_audiosilencer")) System.AudioSilencerHook();
if (mPrefs.getBoolean("system_fw_noblacklist")) System.NoFloatingWindowBlacklistHook();
if (mPrefs.getBoolean("controls_volumecursor")) Controls.VolumeCursorHook();
if (mPrefs.getBoolean("controls_fsg_horiz")) Controls.FSGesturesHook();
if (mPrefs.getBoolean("various_alarmcompat")) Various.AlarmCompatHook();
if (mPrefs.getStringAsInt("system_iconlabletoasts", 1) > 1) System.IconLabelToastsHook();
if (mPrefs.getStringAsInt("system_blocktoasts", 1) > 1) System.SelectiveToastsHook();
//System.AudioSilencerHook();
hideIconsActive =
mPrefs.getBoolean("system_statusbaricons_alarm") ||
@ -165,6 +168,8 @@ public class MainModule implements IXposedHookZygoteInit, IXposedHookLoadPackage
if (mPrefs.getBoolean("system_clearalltasks")) System.ClearAllTasksHook(lpparam);
if (mPrefs.getBoolean("system_snoozedmanager")) System.MoreSnoozeOptionsServiceHook(lpparam);
if (mPrefs.getBoolean("system_nodarkforce")) System.NoDarkForceHook(lpparam);
if (mPrefs.getBoolean("system_audiosilencer")) System.AudioSilencerServiceHook(lpparam);
if (mPrefs.getBoolean("system_fw_sticky")) System.StickyFloatingWindowsHook(lpparam);
if (mPrefs.getBoolean("controls_powerflash")) Controls.PowerKeyHook(lpparam);
if (mPrefs.getBoolean("controls_fingerprintfailure")) Controls.FingerprintHapticFailureHook(lpparam);
if (mPrefs.getBoolean("controls_fingerprintscreen")) Controls.FingerprintScreenOnHook(lpparam);
@ -369,6 +374,7 @@ public class MainModule implements IXposedHookZygoteInit, IXposedHookLoadPackage
if (mPrefs.getStringAsInt("launcher_foldershade", 1) > 1) Launcher.FolderShadeHook(lpparam);
if (mPrefs.getStringAsInt("launcher_closefolders", 1) > 1) Launcher.CloseFolderOnLaunchHook(lpparam);
if (lpparam.packageName.equals("com.miui.home")) {
if (mPrefs.getInt("system_recents_blur", 100) < 100) Launcher.RecentsBlurRatioHook(lpparam);
if (mPrefs.getInt("system_recommended_first_action", 1) > 1 ||
mPrefs.getInt("system_recommended_second_action", 1) > 1 ||
mPrefs.getInt("system_recommended_third_action", 1) > 1 ||
@ -377,7 +383,7 @@ public class MainModule implements IXposedHookZygoteInit, IXposedHookLoadPackage
if (mPrefs.getInt("controls_fsg_width", 100) > 100) Controls.BackGestureAreaWidthHook(lpparam, false);
if (mPrefs.getBoolean("controls_fsg_horiz")) Launcher.FSGesturesHook(lpparam);
if (mPrefs.getBoolean("system_removecleaner")) System.HideMemoryCleanHook(lpparam, true);
if (mPrefs.getBoolean("launcher_fixstatusbarmode")) Launcher.FixStatusBarModeHook(lpparam);
//if (mPrefs.getBoolean("launcher_fixstatusbarmode")) Launcher.FixStatusBarModeHook(lpparam);
if (mPrefs.getBoolean("launcher_fixanim")) Launcher.FixAnimHook(lpparam);
if (mPrefs.getBoolean("launcher_hideseekpoints")) Launcher.HideSeekPointsHook(lpparam);
if (mPrefs.getBoolean("launcher_privacyapps_gest")) Launcher.PrivacyFolderHook(lpparam);


+ 1
- 1
app/src/main/java/name/mikanoshi/customiuizer/PreferenceFragmentBase.java View File

@ -174,7 +174,7 @@ public class PreferenceFragmentBase extends PreferenceFragment {
} catch (Throwable ignore) {}
if (supressMenu) return;
if (actionBar != null) actionBar.showSplitActionBar(false, false);
if (actionBar != null) try { actionBar.showSplitActionBar(false, false); } catch (Throwable ignore) {}
setImmersionMenuEnabled(true);
View view = getView();


+ 3
- 2
app/src/main/java/name/mikanoshi/customiuizer/SnoozedFragment.java View File

@ -49,6 +49,7 @@ public class SnoozedFragment extends PreferenceFragmentBase {
BroadcastReceiver updateReceiver = new BroadcastReceiver() {
@Override
@SuppressWarnings("ConstantConditions")
public void onReceive(Context context, Intent intent) {
handler.removeCallbacks(fetchFailed);
HashMap<String, ArrayList<SnoozeData>> tmpList = new HashMap<String, ArrayList<SnoozeData>>();
@ -96,10 +97,10 @@ public class SnoozedFragment extends PreferenceFragmentBase {
supressMenu = true;
super.onActivityCreated(savedInstanceState);
ActionBar actionBar = getActionBar();
if (actionBar != null) {
if (actionBar != null) try {
actionBar.setTitle(R.string.title_snoozed);
actionBar.showSplitActionBar(true, true);
}
} catch (Throwable ignore) {}
setImmersionMenuEnabled(false);
if (getView() == null) return;


+ 6
- 3
app/src/main/java/name/mikanoshi/customiuizer/mods/Controls.java View File

@ -275,8 +275,11 @@ public class Controls {
protected void before(final MethodHookParam param) throws Throwable {
Application mContext = (Application)XposedHelpers.callStaticMethod(XposedHelpers.findClass("android.app.ActivityThread", null), "currentApplication");
int mStreamType = (int)XposedHelpers.findMethodExact(XposedHelpers.findClass("android.media.MediaPlayer", null), "getAudioStreamType").invoke(param.thisObject);
if (mContext != null && (mStreamType == AudioManager.STREAM_MUSIC || mStreamType == 0x80000000))
mContext.sendBroadcast(new Intent(GlobalActions.ACTION_PREFIX + "SaveLastMusicPausedTime"));
if (mContext != null && (mStreamType == AudioManager.STREAM_MUSIC || mStreamType == 0x80000000)) {
Intent intent = new Intent(GlobalActions.ACTION_PREFIX + "SaveLastMusicPausedTime");
intent.setPackage("android");
mContext.sendBroadcast(intent);
}
}
});
}
@ -289,6 +292,7 @@ public class Controls {
if (act == null) return;
Intent intent = new Intent(GlobalActions.EVENT_PREFIX + "CHANGE_FOCUSED_APP");
intent.putExtra("package", act.getPackageName());
intent.setPackage("android");
act.sendBroadcast(intent);
}
});
@ -668,7 +672,6 @@ public class Controls {
wasScreenOn = (boolean)XposedHelpers.callMethod(param.thisObject, "isScreenOn");
wasFingerprintUsed = Settings.System.getInt(miuiPWMContext.getContentResolver(), "is_fingerprint_active", 0) == 1;
hasDoubleTap = false;
if (wasScreenOn && !wasFingerprintUsed) {
int delay = MainModule.mPrefs.getInt("controls_fingerprintlong_delay", 0);


+ 18
- 1
app/src/main/java/name/mikanoshi/customiuizer/mods/GlobalActions.java View File

@ -12,6 +12,7 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
@ -43,6 +44,7 @@ import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam;
@ -58,6 +60,7 @@ import name.mikanoshi.customiuizer.utils.Helpers;
import name.mikanoshi.customiuizer.utils.Helpers.MethodHook;
import static de.robv.android.xposed.XposedHelpers.findClass;
import static de.robv.android.xposed.XposedHelpers.findClassIfExists;
import static de.robv.android.xposed.XposedHelpers.findField;
import static de.robv.android.xposed.XposedHelpers.findMethodExact;
import static java.lang.System.currentTimeMillis;
@ -205,6 +208,18 @@ public class GlobalActions {
}
if (action.equals(ACTION_PREFIX + "ExpandSettings")) try {
if (Helpers.is12()) {
Object controller = XposedHelpers.callStaticMethod(findClass("com.android.systemui.Dependency", context.getClassLoader()), "get", findClassIfExists("com.android.systemui.miui.statusbar.policy.ControlPanelController", context.getClassLoader()));
boolean isUseControlCenter = (boolean)XposedHelpers.callMethod(controller, "isUseControlCenter");
if (isUseControlCenter) {
if ((boolean)XposedHelpers.callMethod(controller, "isQSFullyCollapsed"))
XposedHelpers.callMethod(controller, "openPanel");
else
XposedHelpers.callMethod(controller, "collapsePanel", true);
return;
}
}
Object mNotificationPanel = XposedHelpers.getObjectField(mStatusBar, "mNotificationPanel");
boolean mPanelExpanded = (boolean)XposedHelpers.getObjectField(mNotificationPanel, "mPanelExpanded");
boolean mQsExpanded = (boolean)XposedHelpers.getObjectField(mNotificationPanel, "mQsExpanded");
@ -771,6 +786,7 @@ public class GlobalActions {
if (param.args[1] != null) try {
Intent intent = new Intent("name.mikanoshi.customiuizer.SAVEEXCEPTION");
intent.putExtra("throwable", (Throwable)param.args[1]);
intent.setPackage(Helpers.modulePkg);
ctx.sendBroadcast(intent);
} catch (Throwable t) {}
}
@ -811,6 +827,7 @@ public class GlobalActions {
Intent fullscreenIntent = new Intent(EVENT_PREFIX + "CHANGE_FULLSCREEN");
boolean isFullScreen = flags != 0 && !"com.android.systemui".equals(act.getPackageName()) && (flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) == WindowManager.LayoutParams.FLAG_FULLSCREEN;
fullscreenIntent.putExtra("fullscreen", isFullScreen);
fullscreenIntent.setPackage("android");
act.sendBroadcast(fullscreenIntent);
}
});
@ -1036,7 +1053,7 @@ public class GlobalActions {
public static boolean expandEQS(Context context) {
try {
context.sendBroadcast(new Intent(ACTION_PREFIX + "ExpandSettings"));
return false;
return true;
} catch (Throwable t) {
XposedBridge.log(t);
return false;


+ 39
- 0
app/src/main/java/name/mikanoshi/customiuizer/mods/Launcher.java View File

@ -1398,6 +1398,45 @@ public class Launcher {
// });
}
public static void RecentsBlurRatioHook(LoadPackageParam lpparam) {
Helpers.hookAllConstructors("com.miui.home.recents.views.RecentsView", lpparam.classLoader, new MethodHook() {
@Override
protected void after(MethodHookParam param) throws Throwable {
XposedHelpers.setFloatField(param.thisObject, "mDefaultScrimAlpha", 0.15f);
XposedHelpers.setObjectField(param.thisObject, "mBackgroundScrim", new ColorDrawable(Color.argb(38, 0, 0, 0)).mutate());
}
});
Helpers.hookAllConstructors("com.miui.home.recents.RecentsViewStateController", lpparam.classLoader, new MethodHook() {
@Override
protected void after(MethodHookParam param) throws Throwable {
Context mContext = (Context)param.args[0];
Handler mHandler = new Handler(mContext.getMainLooper());
new Helpers.SharedPrefObserver(mContext, mHandler, "pref_key_system_recents_blur", 100) {
@Override
public void onChange(String name, int defValue) {
MainModule.mPrefs.put(name, Helpers.getSharedIntPref(mContext, name, 100));
}
};
}
});
Helpers.hookAllMethods("com.miui.home.launcher.common.Utilities", lpparam.classLoader, "startBlurAnim", new MethodHook() {
@Override
protected void before(MethodHookParam param) throws Throwable {
param.args[2] = (float)param.args[2] * MainModule.mPrefs.getInt("system_recents_blur", 100) / 100f;
}
});
Helpers.findAndHookMethod("com.miui.home.launcher.common.Utilities", lpparam.classLoader, "fastBlur", float.class, Window.class, new MethodHook() {
@Override
protected void before(MethodHookParam param) throws Throwable {
param.args[0] = (float)param.args[0] * MainModule.mPrefs.getInt("system_recents_blur", 100) / 100f;
}
});
}
// public static void NoInternationalBuildHook(LoadPackageParam lpparam) {
// XposedHelpers.setStaticBooleanField(XposedHelpers.findClass("miui.os.Build", null), "IS_INTERNATIONAL_BUILD", false);
// }


+ 269
- 54
app/src/main/java/name/mikanoshi/customiuizer/mods/System.java View File

@ -7,6 +7,7 @@ import android.animation.ObjectAnimator;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.Application;
import android.app.Dialog;
import android.app.KeyguardManager;
@ -51,7 +52,6 @@ import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.hardware.usb.UsbManager;
import android.media.AudioManager;
import android.media.MediaDataSource;
import android.media.MediaMetadata;
import android.media.MediaPlayer;
import android.media.SoundPool;
@ -148,6 +148,7 @@ import java.util.Set;
import java.util.TimeZone;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.TimeUnit;
@ -173,6 +174,8 @@ import name.mikanoshi.customiuizer.utils.BatteryIndicator;
import name.mikanoshi.customiuizer.utils.Helpers;
import name.mikanoshi.customiuizer.utils.Helpers.MethodHook;
import name.mikanoshi.customiuizer.utils.Helpers.MimeType;
import name.mikanoshi.customiuizer.utils.SoundData;
import static name.mikanoshi.customiuizer.mods.GlobalActions.ACTION_PREFIX;
public class System {
@ -398,7 +401,7 @@ public class System {
if (mContext == null)
Helpers.log("checkBTConnections", "mContext is NULL!");
else
mContext.sendBroadcast(new Intent(GlobalActions.ACTION_PREFIX + "UnlockBTConnection"));
mContext.sendBroadcast(new Intent(ACTION_PREFIX + "UnlockBTConnection"));
}
// private static void setLockScreenDisabled(ClassLoader classLoader, Object thisObject, boolean state) {
@ -451,7 +454,7 @@ public class System {
XposedBridge.log(t);
}
}
}, new IntentFilter(GlobalActions.ACTION_PREFIX + "UnlockStrongAuth"));
}, new IntentFilter(ACTION_PREFIX + "UnlockStrongAuth"));
}
});
@ -475,7 +478,7 @@ public class System {
}
isUnlockedInnerCall = true;
XposedHelpers.callMethod(XposedHelpers.getObjectField(param.thisObject, "mUpdateMonitor"), "reportSuccessfulStrongAuthUnlockAttempt");
Intent unlockIntent = new Intent(GlobalActions.ACTION_PREFIX + "UnlockStrongAuth");
Intent unlockIntent = new Intent(ACTION_PREFIX + "UnlockStrongAuth");
mContext.sendBroadcast(unlockIntent);
}
}
@ -487,14 +490,14 @@ public class System {
Context mContext = (Context)XposedHelpers.getObjectField(param.thisObject, "mContext");
IntentFilter filter = new IntentFilter();
filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
filter.addAction(GlobalActions.ACTION_PREFIX + "UnlockSetForced");
filter.addAction(GlobalActions.ACTION_PREFIX + "UnlockBTConnection");
filter.addAction(ACTION_PREFIX + "UnlockSetForced");
filter.addAction(ACTION_PREFIX + "UnlockBTConnection");
mContext.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(GlobalActions.ACTION_PREFIX + "UnlockSetForced"))
if (action.equals(ACTION_PREFIX + "UnlockSetForced"))
forcedOption = intent.getIntExtra("system_noscreenlock_force", -1);
boolean isShowing = (boolean)XposedHelpers.callMethod(param.thisObject, "isShowing");
@ -506,7 +509,7 @@ public class System {
if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
NetworkInfo netInfo = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
if (netInfo.isConnected()) isTrusted = isTrustedWiFi(mContext);
} else if (action.equals(GlobalActions.ACTION_PREFIX + "UnlockBTConnection")) {
} else if (action.equals(ACTION_PREFIX + "UnlockBTConnection")) {
isTrusted = isTrustedBt(lpparam.classLoader);
}
@ -521,7 +524,7 @@ public class System {
XposedHelpers.callMethod(param.thisObject, "resetStateLocked");
isUnlockedInnerCall = true;
XposedHelpers.callMethod(XposedHelpers.getObjectField(param.thisObject, "mUpdateMonitor"), "reportSuccessfulStrongAuthUnlockAttempt");
Intent unlockIntent = new Intent(GlobalActions.ACTION_PREFIX + "UnlockStrongAuth");
Intent unlockIntent = new Intent(ACTION_PREFIX + "UnlockStrongAuth");
mContext.sendBroadcast(unlockIntent);
}
}
@ -603,9 +606,10 @@ public class System {
if (mDevice != null) deviceList.add(mDevice);
}
updateIntent.putParcelableArrayListExtra("device_list", deviceList);
updateIntent.setPackage(Helpers.modulePkg);
mContext.sendBroadcast(updateIntent);
}
}, new IntentFilter(GlobalActions.ACTION_PREFIX + "FetchCachedDevices"));
}, new IntentFilter(ACTION_PREFIX + "FetchCachedDevices"));
}
});
@ -1043,7 +1047,7 @@ public class System {
Set<String> selectedApps = Helpers.getSharedStringSetPref(mContext, "pref_key_system_popupnotif_apps");
String pkgName = (String)XposedHelpers.callMethod(param.args[0], "getPackageName");
if (selectedApps.contains(pkgName)) {
Intent expandNotif = new Intent(GlobalActions.ACTION_PREFIX + "ExpandNotifications");
Intent expandNotif = new Intent(ACTION_PREFIX + "ExpandNotifications");
expandNotif.putExtra("expand_only", true);
mContext.sendBroadcast(expandNotif);
}
@ -1524,7 +1528,8 @@ public class System {
}
});
Helpers.findAndHookMethod(nscCls, "updateNetworkSpeed", new MethodHook() {
Method asyncMethod = XposedHelpers.findMethodExactIfExists(nscCls, "updateNetworkSpeedAsync");
Helpers.findAndHookMethod(nscCls, asyncMethod != null ? "updateNetworkSpeedAsync" : "updateNetworkSpeed", new MethodHook() {
@Override
protected void before(final MethodHookParam param) throws Throwable {
boolean isConnected = false;
@ -1803,12 +1808,14 @@ public class System {
MotionEvent me = (MotionEvent)param.args[0];
if (me.getActionMasked() == MotionEvent.ACTION_DOWN) {
boolean mAllowSwipingDown = true;
if (Helpers.is12()) {
if (Helpers.is12()) try {
Object mPickedChild = XposedHelpers.getObjectField(param.thisObject, "mPickedChild");
if (mPickedChild != null) {
View mMiniBar = (View)XposedHelpers.callMethod(mPickedChild, "getMiniWindowBar");
if (mMiniBar != null && mMiniBar.getVisibility() == View.VISIBLE) mAllowSwipingDown = false;
}
} catch (Throwable t) {
XposedBridge.log(t);
}
XposedHelpers.setAdditionalInstanceField(param.thisObject, "mAllowSwipingDown", mAllowSwipingDown);
}
@ -1829,7 +1836,7 @@ public class System {
return;
}
Intent expandNotif = new Intent(GlobalActions.ACTION_PREFIX + "ExpandNotifications");
Intent expandNotif = new Intent(ACTION_PREFIX + "ExpandNotifications");
expandNotif.putExtra("expand_only", true);
mContext.sendBroadcast(expandNotif);
}
@ -2607,7 +2614,7 @@ public class System {
SystemProperties.set("ctl.restart", "zygote");
custom = true;
} else if ("killsysui".equals(cmd)) {
mContext.sendBroadcast(new Intent(GlobalActions.ACTION_PREFIX + "RestartSystemUI"));
mContext.sendBroadcast(new Intent(ACTION_PREFIX + "RestartSystemUI"));
// final WallpaperManager wm = (WallpaperManager)mContext.getSystemService(Context.WALLPAPER_SERVICE);
// Drawable drawable = wm.getDrawable();
// ActivityManager am = (ActivityManager)mContext.getSystemService(Context.ACTIVITY_SERVICE);
@ -4536,6 +4543,7 @@ public class System {
LayoutInflater inflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
int layoutResId = mContext.getResources().getIdentifier("miui_keyguard_left_view_control_center_item", "layout", lpparam.packageName);
if (layoutResId == 0) layoutResId = mContext.getResources().getIdentifier("miui_keyguard_left_view_item", "layout", lpparam.packageName);
int imgResId = mContext.getResources().getIdentifier("keyguard_left_list_item_img", "id", lpparam.packageName);
int nameResId = mContext.getResources().getIdentifier("keyguard_left_list_item_name", "id", lpparam.packageName);
//int numberResId = mContext.getResources().getIdentifier("keyguard_left_list_item_number", "id", lpparam.packageName);
@ -4761,7 +4769,7 @@ public class System {
try {
if (mContext == null) return;
String pkgName = (String)XposedHelpers.callMethod(controller, "getPackageName");
Intent intent = new Intent(GlobalActions.ACTION_PREFIX + "UpdateMediaPosition:" + pkgName);
Intent intent = new Intent(ACTION_PREFIX + "UpdateMediaPosition:" + pkgName);
MediaMetadata medaData = controller.getMetadata();
if (medaData == null) return;
intent.putExtra(MediaMetadata.METADATA_KEY_DURATION, medaData.getLong(MediaMetadata.METADATA_KEY_DURATION));
@ -4823,7 +4831,7 @@ public class System {
MediaControllerReceiver mSeekToReceiver = (MediaControllerReceiver)XposedHelpers.getAdditionalInstanceField(param.thisObject, "mSeekToReceiver");
if (newActive)
mContext.registerReceiver(mSeekToReceiver, new IntentFilter(GlobalActions.ACTION_PREFIX + "SeekToMediaPosition:" + mContext.getPackageName()));
mContext.registerReceiver(mSeekToReceiver, new IntentFilter(ACTION_PREFIX + "SeekToMediaPosition:" + mContext.getPackageName()));
else
mContext.unregisterReceiver(mSeekToReceiver);
}
@ -4931,7 +4939,7 @@ public class System {
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
seekBar.setTag(false);
Intent intent = new Intent(GlobalActions.ACTION_PREFIX + "SeekToMediaPosition:" + pkgName);
Intent intent = new Intent(ACTION_PREFIX + "SeekToMediaPosition:" + pkgName);
intent.putExtra("android.media.metadata.POSITION", Long.valueOf(seekBar.getProgress()));
seekBar.getContext().sendBroadcast(intent);
}
@ -4964,7 +4972,7 @@ public class System {
}
}
};
mView.getContext().registerReceiver(seekBarUpdate, new IntentFilter(GlobalActions.ACTION_PREFIX + "UpdateMediaPosition:" + pkgName));
mView.getContext().registerReceiver(seekBarUpdate, new IntentFilter(ACTION_PREFIX + "UpdateMediaPosition:" + pkgName));
}
});
}
@ -6154,9 +6162,9 @@ public class System {
@SuppressWarnings("unchecked")
protected void after(MethodHookParam param) throws Throwable {
IntentFilter filter = new IntentFilter();
filter.addAction(GlobalActions.ACTION_PREFIX + "GetSnoozedNotifications");
filter.addAction(GlobalActions.ACTION_PREFIX + "UnsnoozeNotification");
filter.addAction(GlobalActions.ACTION_PREFIX + "CancelNotification");
filter.addAction(ACTION_PREFIX + "GetSnoozedNotifications");
filter.addAction(ACTION_PREFIX + "UnsnoozeNotification");
filter.addAction(ACTION_PREFIX + "CancelNotification");
Context mContext = (Context)XposedHelpers.getObjectField(param.thisObject, "mContext");
mContext.registerReceiver(new BroadcastReceiver() {
@Override
@ -6165,7 +6173,7 @@ public class System {
ArrayMap<Integer, ArrayMap<String, ArrayMap<String, Object>>> mSnoozedNotifications = (ArrayMap<Integer, ArrayMap<String, ArrayMap<String, Object>>>)XposedHelpers.getObjectField(param.thisObject, "mSnoozedNotifications");
ArrayMap<String, Long> mSnoozedNotificationDelays = (ArrayMap<String, Long>)XposedHelpers.getAdditionalInstanceField(param.thisObject, "mSnoozedNotificationDelays");
if (action.equals(GlobalActions.ACTION_PREFIX + "CancelNotification")) try {
if (action.equals(ACTION_PREFIX + "CancelNotification")) try {
ArrayMap<String, ArrayMap<String, Object>> packages = mSnoozedNotifications.get(intent.getIntExtra("user", 0));
if (packages == null) return;
ArrayMap<String, Object> notificatios = packages.get(intent.getStringExtra("package"));
@ -6177,7 +6185,7 @@ public class System {
XposedBridge.log(t);
}
if (action.equals(GlobalActions.ACTION_PREFIX + "UnsnoozeNotification")) try {
if (action.equals(ACTION_PREFIX + "UnsnoozeNotification")) try {
XposedHelpers.callMethod(param.thisObject, "repost", intent.getStringExtra("key"), intent.getIntExtra("user", 0));
} catch (Throwable t) {
XposedBridge.log(t);
@ -6573,14 +6581,55 @@ public class System {
});
}
@SuppressWarnings({"unchecked", "unused"})
public static ArrayList<SoundData> mLastPlayedSounds = new ArrayList<SoundData>();
public static void AudioSilencerServiceHook(LoadPackageParam lpparam) {
Helpers.hookAllMethods("com.android.server.policy.PhoneWindowManager", lpparam.classLoader, "init", new MethodHook() {
@Override
protected void after(MethodHookParam param) throws Throwable {
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_PREFIX + "SavePlayedSound");
filter.addAction(ACTION_PREFIX + "FetchPlayedSounds");
Context mContext = (Context)XposedHelpers.getObjectField(param.thisObject, "mContext");
mContext.registerReceiver(new BroadcastReceiver() {
public void onReceive(final Context context, Intent intent) {
String action = intent.getAction();
if (action != null) try {
if (action.equals(ACTION_PREFIX + "SavePlayedSound")) {
SoundData data = intent.getParcelableExtra("data");
mLastPlayedSounds.add(0, data);
if (mLastPlayedSounds.size() > 10)
mLastPlayedSounds = new ArrayList<SoundData>(mLastPlayedSounds.subList(0, 10));
} else if (action.equals(ACTION_PREFIX + "FetchPlayedSounds")) {
Intent soundsIntent = new Intent(GlobalActions.EVENT_PREFIX + "FetchPlayedSoundsData");
soundsIntent.putParcelableArrayListExtra("sounds", mLastPlayedSounds);
soundsIntent.setPackage(Helpers.modulePkg);
mContext.sendBroadcast(soundsIntent);
}
} catch (Throwable t) {
XposedBridge.log(t);
}
}
}, filter);
}
});
}
public static void SavePlayedSound(Context context, SoundData data) {
Intent saveSoundIntent = new Intent(ACTION_PREFIX + "SavePlayedSound");
saveSoundIntent.putExtra("data", data);
saveSoundIntent.setPackage("android");
context.sendBroadcast(saveSoundIntent);
}
@SuppressWarnings({"unchecked"})
public static void AudioSilencerHook() {
Helpers.hookAllConstructors(SoundPool.class, new MethodHook() {
@Override
protected void after(MethodHookParam param) throws Throwable {
if (XposedHelpers.getAdditionalInstanceField(param.thisObject, "mSourceHashes") == null) {
SparseArray<String> mSourceHashes = new SparseArray<String>();
XposedHelpers.setAdditionalInstanceField(param.thisObject, "mSourceHashes", mSourceHashes);
if (XposedHelpers.getAdditionalInstanceField(param.thisObject, "mSourceSoundData") == null) {
SparseArray<SoundData> mSourceSoundData = new SparseArray<SoundData>();
XposedHelpers.setAdditionalInstanceField(param.thisObject, "mSourceSoundData", mSourceSoundData);
}
}
});
@ -6588,19 +6637,15 @@ public class System {
Helpers.hookAllMethods(SoundPool.class, "load", new MethodHook() {
@Override
protected void after(MethodHookParam param) throws Throwable {
SparseArray<String> mSourceHashes = (SparseArray<String>)XposedHelpers.getAdditionalInstanceField(param.thisObject, "mSourceHashes");
SparseArray<SoundData> mSourceSoundData = (SparseArray<SoundData>)XposedHelpers.getAdditionalInstanceField(param.thisObject, "mSourceSoundData");
Application callerContext = (Application)XposedHelpers.callStaticMethod(XposedHelpers.findClass("android.app.ActivityThread", null), "currentApplication");
if (callerContext == null) return;
String caller = callerContext.getPackageName();
if (param.args[0] instanceof Context) {
Context mContext = (Context)param.args[0];
String hash = "res|" + caller + "|" + mContext.getResources().getResourceName((int)param.args[1]);
XposedBridge.log(param.getResult() + " | " + hash);
mSourceHashes.put((int)param.getResult(), hash);
mSourceSoundData.put((int)param.getResult(), new SoundData(caller, "resource", mContext.getResources().getResourceName((int)param.args[1])));
} else if (param.args[0] instanceof String) {
String hash = "file|" + caller + "|" + param.args[0];
XposedBridge.log(param.getResult() + " | " + hash);
mSourceHashes.put((int)param.getResult(), hash);
mSourceSoundData.put((int)param.getResult(), new SoundData(caller, "file", (String)param.args[0]));
}
}
});
@ -6608,9 +6653,15 @@ public class System {
Helpers.hookAllMethods(SoundPool.class, "play", new MethodHook() {
@Override
protected void before(MethodHookParam param) throws Throwable {
SparseArray<String> mSourceHashes = (SparseArray<String>)XposedHelpers.getAdditionalInstanceField(param.thisObject, "mSourceHashes");
if (mSourceHashes == null) return;
XposedBridge.log("Playing [" + param.args[0] + "] " + mSourceHashes.get((Integer)param.args[0]));
SparseArray<SoundData> mSourceSoundData = (SparseArray<SoundData>)XposedHelpers.getAdditionalInstanceField(param.thisObject, "mSourceSoundData");
if (mSourceSoundData != null) {
Application mContext = (Application)XposedHelpers.callStaticMethod(XposedHelpers.findClass("android.app.ActivityThread", null), "currentApplication");
if (mContext == null) return;
SoundData data = mSourceSoundData.get((Integer)param.args[0]);
SavePlayedSound(mContext, data);
Set<String> silencedSounds = Helpers.getSharedStringSetPref(mContext, "pref_key_system_audiosilencer_sounds");
if (silencedSounds.contains(data.toPref())) param.setResult(null);
}
}
});
@ -6621,28 +6672,27 @@ public class System {
Application callerContext = (Application)XposedHelpers.callStaticMethod(XposedHelpers.findClass("android.app.ActivityThread", null), "currentApplication");
if (callerContext == null) return;
String caller = callerContext.getPackageName();
String hash = null;
if (param.args.length > 1 && param.args[0] instanceof Context && param.args[1] instanceof Uri) {
hash = "uri|" + caller + "|" + ((Uri)param.args[1]).getPath();
XposedBridge.log(hash);
} else if (param.args[0] instanceof String) {
hash = "file|" + caller + "|" + param.args[0];
XposedBridge.log(hash);
} else if (param.args[0] instanceof MediaDataSource) {
hash = "mds|" + caller + "|" + param.args[0];
XposedBridge.log(hash);
}
if (hash != null)
XposedHelpers.setAdditionalInstanceField(param.thisObject, "mSourceHash", hash);
SoundData soundData = null;
if (param.args.length > 1 && param.args[0] instanceof Context && param.args[1] instanceof Uri)
soundData = new SoundData(caller, "uri", ((Uri)param.args[1]).getPath());
else if (param.args[0] instanceof String)
soundData = new SoundData(caller, "file", (String)param.args[0]);
if (soundData != null)
XposedHelpers.setAdditionalInstanceField(param.thisObject, "mSourceSoundData", soundData);
}
});
Helpers.hookAllMethods(MediaPlayer.class, "start", new MethodHook() {
@Override
protected void before(MethodHookParam param) throws Throwable {
String mSourceHash = (String)XposedHelpers.getAdditionalInstanceField(param.thisObject, "mSourceHash");
if (mSourceHash == null) return;
XposedBridge.log("Playing " + mSourceHash);
SoundData mSourceSoundData = (SoundData)XposedHelpers.getAdditionalInstanceField(param.thisObject, "mSourceSoundData");
if (mSourceSoundData != null) {
Application mContext = (Application)XposedHelpers.callStaticMethod(XposedHelpers.findClass("android.app.ActivityThread", null), "currentApplication");
if (mContext == null) return;
SavePlayedSound(mContext, mSourceSoundData);
Set<String> silencedSounds = Helpers.getSharedStringSetPref(mContext, "pref_key_system_audiosilencer_sounds");
if (silencedSounds.contains(mSourceSoundData.toPref())) param.setResult(null);
}
}
});
}
@ -6676,6 +6726,171 @@ public class System {
});
}
public static void NoFloatingWindowBlacklistHook() {
MethodHook clearHook = new MethodHook() {
@Override
@SuppressWarnings("unchecked")
protected void after(MethodHookParam param) throws Throwable {
List<String> blackList = (List<String>)param.getResult();
if (blackList != null) blackList.clear();
param.setResult(blackList);
}
};
Helpers.findAndHookMethod("android.util.MiuiMultiWindowAdapter", null, "getFreeformBlackList", clearHook);
Helpers.findAndHookMethod("android.util.MiuiMultiWindowAdapter", null, "getFreeformBlackListFromCloud", Context.class, clearHook);
}
public static ConcurrentHashMap<String, Pair<Float, Rect>> fwApps = new ConcurrentHashMap<String, Pair<Float, Rect>>();
public static String getTaskPackageName(Object thisObject, int taskId) {
return getTaskPackageName(thisObject, taskId, false, null);
}
public static String getTaskPackageName(Object thisObject, int taskId, ActivityOptions options) {
return getTaskPackageName(thisObject, taskId, true, options);
}
public static String getTaskPackageName(Object thisObject, int taskId, boolean withOptions, ActivityOptions options) {
Object mRootActivityContainer = XposedHelpers.getObjectField(thisObject, "mRootActivityContainer");
if (mRootActivityContainer == null) return null;
Object task = withOptions ?
XposedHelpers.callMethod(mRootActivityContainer, "anyTaskForId", taskId, 2, options, true) :
XposedHelpers.callMethod(mRootActivityContainer, "anyTaskForId", taskId, 0);
if (task == null) return null;
Intent intent = (Intent)XposedHelpers.getObjectField(task, "intent");
return intent == null ? null : intent.getComponent().getPackageName();
}
public static String serializeFwApps() {
StringBuilder data = new StringBuilder();
for (Map.Entry<String, Pair<Float, Rect>> entry: fwApps.entrySet()) {
Pair<Float, Rect> val = entry.getValue();
data.append(entry.getKey());
data.append(":");
data.append(val.first);
data.append(":");
data.append(val.second == null ? "-" : val.second.flattenToString());
data.append("|");
}
return data.toString().replaceFirst("\\|$", "");
}
public static void unserializeFwApps(String data) {
fwApps.clear();
if (data == null || "".equals(data)) return;
String[] dataArr = data.split("\\|");
for (String appData: dataArr) {
if ("".equals(appData)) continue;
String[] appDataArr = appData.split(":");
fwApps.put(appDataArr[0], new Pair<Float, Rect>(Float.parseFloat(appDataArr[1]), "-".equals(appDataArr[2]) ? null : Rect.unflattenFromString(appDataArr[2])));
}
}
public static void storeFwAppsInSetting(Context context) {
Settings.Global.putString(context.getContentResolver(), Helpers.modulePkg + ".fw.apps", serializeFwApps());
}
public static void restoreFwAppsInSetting(Context context) {
unserializeFwApps(Settings.Global.getString(context.getContentResolver(), Helpers.modulePkg + ".fw.apps"));
}
public static void StickyFloatingWindowsHook(LoadPackageParam lpparam) {
Helpers.hookAllMethods("com.android.server.wm.ActivityStarterInjector", lpparam.classLoader, "modifyLaunchActivityOptionIfNeed", new MethodHook() {
@Override
protected void after(MethodHookParam param) throws Throwable {
if (param.args.length != 8) return;
Intent intent = (Intent)param.args[5];
if (intent == null || intent.getComponent() == null) return;
ActivityOptions options = (ActivityOptions)param.getResult();
int windowingMode = options == null ? -1 : (int)XposedHelpers.callMethod(options, "getLaunchWindowingMode");
String pkgName = intent.getComponent().getPackageName();
if (windowingMode != 5 && fwApps.containsKey(pkgName)) try {
Class<?> mmwuCls = findClassIfExists("android.util.MiuiMultiWindowUtils", null);
if (mmwuCls == null) {
Helpers.log("StickyFloatingWindowsHook", "Cannot find MiuiMultiWindowUtils class");
return;
}
Context mContext = (Context)XposedHelpers.getObjectField(param.args[0], "mContext");
//options = (ActivityOptions)XposedHelpers.callStaticMethod(mmwuCls, "getActivityOptions", mContext, pkgName, true, false);
if (options == null) options = ActivityOptions.makeBasic();
XposedHelpers.callMethod(options, "setLaunchWindowingMode", 5);
XposedHelpers.callMethod(options, "setMiuiConfigFlag", 2);
Float scale;
Rect rect;
Pair<Float, Rect> values = fwApps.get(pkgName);
if (values == null || values.first == 0f || values.second == null) {
scale = XposedHelpers.getStaticFloatField(mmwuCls, "sScale");
rect = (Rect)XposedHelpers.callStaticMethod(mmwuCls, "getFreeformRect", mContext);
} else {
scale = values.first;
rect = values.second;
}
options.setLaunchBounds(rect);
try {
Object injector = XposedHelpers.callMethod(options, "getActivityOptionsInjector");
XposedHelpers.callMethod(injector, "setFreeformScale", scale);
} catch (Throwable ignore) {}
param.setResult(options);
} catch (Throwable t) {
XposedBridge.log(t);
}
}
});
Helpers.hookAllMethods("com.android.server.wm.ActivityStackSupervisor", lpparam.classLoader, "startActivityFromRecents", new MethodHook() {
@Override
protected void after(MethodHookParam param) throws Throwable {
Object safeOptions = param.args[3];
ActivityOptions options = (ActivityOptions)XposedHelpers.callMethod(safeOptions, "getOptions", param.thisObject);
int windowingMode = options == null ? -1 : (int)XposedHelpers.callMethod(options, "getLaunchWindowingMode");
if (windowingMode != 5) return;
String pkgName = getTaskPackageName(param.thisObject, (int)param.args[2], options);
if (pkgName != null) {
fwApps.put(pkgName, new Pair<Float, Rect>(0f, null));
storeFwAppsInSetting((Context)XposedHelpers.getObjectField(XposedHelpers.getObjectField(param.thisObject, "mService"), "mContext"));
}
}
});
Helpers.hookAllMethods("com.android.server.wm.MiuiFreeFormGestureController", lpparam.classLoader, "notifyFullScreenWidnowModeStart", new MethodHook() {
@Override
protected void before(MethodHookParam param) throws Throwable {
String pkgName = (String)XposedHelpers.getObjectField(param.thisObject, "mFreeFormPackageName");
if (fwApps.remove(pkgName) != null)
storeFwAppsInSetting((Context)XposedHelpers.getObjectField(XposedHelpers.getObjectField(param.thisObject, "mService"), "mContext"));
}
});
// Helpers.hookAllMethods("com.android.server.wm.MiuiFreeFormGesturePointerEventListener", lpparam.classLoader, "startShowFullScreenWindow", new MethodHook() {
// @Override
// protected void before(MethodHookParam param) throws Throwable {
// Object mGestureController = XposedHelpers.getObjectField(param.thisObject, "mGestureController");
// XposedBridge.log("FULLSCREEN: " + XposedHelpers.getObjectField(mGestureController, "mFreeFormPackageName"));
// }
// });
Helpers.findAndHookMethod("com.android.server.wm.ActivityTaskManagerService", lpparam.classLoader, "onSystemReady", new MethodHook() {
@Override
protected void after(MethodHookParam param) throws Throwable {
restoreFwAppsInSetting((Context)XposedHelpers.getObjectField(param.thisObject, "mContext"));
}
});
Helpers.hookAllMethods("com.android.server.wm.ActivityTaskManagerService", lpparam.classLoader, "resizeTask", new MethodHook() {
@Override
protected void before(MethodHookParam param) throws Throwable {
float sScale = XposedHelpers.getStaticFloatField(findClass("android.util.MiuiMultiWindowUtils", null), "sScale");
String pkgName = getTaskPackageName(param.thisObject, (int)param.args[0]);
if (pkgName != null && fwApps.containsKey(pkgName)) {
fwApps.put(pkgName, new Pair<Float, Rect>(sScale, new Rect((Rect)param.args[1])));
storeFwAppsInSetting((Context)XposedHelpers.getObjectField(param.thisObject, "mContext"));
}
}
});
}
// @SuppressWarnings("unchecked")
// public static void MultiWindowHook() {
// HashMap<String, Integer> sAppList = (HashMap<String, Integer>)XposedHelpers.getStaticObjectField(findClass("android.util.MiuiMultiWindowUtils", null), "sAppList");


+ 12
- 8
app/src/main/java/name/mikanoshi/customiuizer/subs/BTList.java View File

@ -46,6 +46,7 @@ public class BTList extends SubFragment {
public void onReceive(Context context, Intent intent) {
ArrayList<BluetoothDevice> deviceList = intent.getParcelableArrayListExtra("device_list");
btList.clear();
if (deviceList != null)
for (BluetoothDevice device: deviceList)
btList.add(new Pair<String, String>(device.getAddress(), device.getName()));
btAdapter1.notifyDataSetChanged();
@ -83,12 +84,13 @@ public class BTList extends SubFragment {
cat2.setBackgroundResource(resId);
@SuppressLint("CutPasteId") ViewStub locationStub = getView().findViewById(R.id.fetch_devices);
locationStub.setLayoutResource(Helpers.is11() ? R.layout.pref_item11 : R.layout.pref_item);
locationStub.setLayoutResource(R.layout.pref_item);
locationStub.inflate();
@SuppressLint("CutPasteId") View location = getView().findViewById(R.id.fetch_devices);
((TextView)location.findViewById(android.R.id.title)).setText(R.string.bt_fetch_devices_title);
((TextView)location.findViewById(android.R.id.summary)).setText(R.string.bt_fetch_devices_summ);
Helpers.setMiuiPrefItem(location);
location.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@ -139,7 +141,9 @@ public class BTList extends SubFragment {
};
void fetchCachedDevices() {
getActivity().sendBroadcast(new Intent(GlobalActions.ACTION_PREFIX + "FetchCachedDevices"));
Intent intent = new Intent(GlobalActions.ACTION_PREFIX + "FetchCachedDevices");
intent.setPackage("com.android.systemui");
getActivity().sendBroadcast(intent);
}
void updateProgressBar() {
@ -148,9 +152,7 @@ public class BTList extends SubFragment {
void registerReceivers() {
unregisterReceivers();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(GlobalActions.EVENT_PREFIX + "CACHEDDEVICESUPDATE");
getActivity().registerReceiver(devicesReceiver, intentFilter);
getActivity().registerReceiver(devicesReceiver, new IntentFilter(GlobalActions.EVENT_PREFIX + "CACHEDDEVICESUPDATE"));
handler.postDelayed(getCachedDevices, 1000);
}
@ -216,10 +218,12 @@ public class BTList extends SubFragment {
public View getView(final int position, View convertView, ViewGroup parent) {
View row;
if (convertView != null)
if (convertView != null) {
row = convertView;
else
row = mInflater.inflate(Helpers.is11() ? R.layout.pref_item11 : R.layout.pref_item, parent, false);
} else {
row = mInflater.inflate(R.layout.pref_item, parent, false);
Helpers.setMiuiPrefItem(row);
}
TextView itemTitle = row.findViewById(android.R.id.title);
TextView itemSumm = row.findViewById(android.R.id.summary);


+ 5
- 0
app/src/main/java/name/mikanoshi/customiuizer/subs/CategorySelector.java View File

@ -21,6 +21,11 @@ public class CategorySelector extends SubFragment {
Bundle args = getArguments();
cat = args.getString("cat");
if ("pref_key_system".equals(cat)) {
if (!Helpers.is12())
((PreferenceScreen)findPreference("pref_key_cat")).removePreference(findPreference("pref_key_system_cat_floatingwindows"));
}
PreferenceScreen screen = (PreferenceScreen)findPreference("pref_key_cat");
int cnt = screen.getPreferenceCount();
for (int i = 0; i < cnt; i++)


+ 2
- 2
app/src/main/java/name/mikanoshi/customiuizer/subs/MultiAction.java View File

@ -87,8 +87,8 @@ public class MultiAction extends SubFragment {
actionSpinner.entries = getResources().getStringArray(entriesResId);
actionSpinner.entryValues = getResources().getIntArray(entryValuesResId);
actionSpinner.setTag(key + "_action");
if (key.equals("pref_key_launcher_swipedown"))
actionSpinner.addDisabledItems(1);
//if (key.equals("pref_key_launcher_swipedown"))
//actionSpinner.addDisabledItems(1);
actionSpinner.init(Helpers.prefs.getInt(key + "_action", 1));
actionSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override


+ 2
- 1
app/src/main/java/name/mikanoshi/customiuizer/subs/SortableList.java View File

@ -22,6 +22,7 @@ import name.mikanoshi.customiuizer.SubFragment;
import name.mikanoshi.customiuizer.utils.Helpers;
import name.mikanoshi.customiuizer.utils.PreferenceAdapter;
@SuppressWarnings("ConstantConditions")
public class SortableList extends SubFragment {
String key;
@ -39,7 +40,7 @@ public class SortableList extends SubFragment {
supressMenu = true;
super.onActivityCreated(savedInstanceState);
ActionBar actionBar = getActionBar();
if (actionBar != null) actionBar.showSplitActionBar(true, true);
if (actionBar != null) try { actionBar.showSplitActionBar(true, true); } catch (Throwable ignore) {}
Bundle args = getArguments();
key = args.getString("key");


+ 9
- 0
app/src/main/java/name/mikanoshi/customiuizer/subs/System.java View File

@ -71,6 +71,15 @@ public class System extends SubFragment {
return true;
}
});
findPreference("pref_key_system_audiosilencer_cat").setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
Bundle args = new Bundle();
args.putString("key", "pref_key_system_audiosilencer_sounds");
openSubFragment(new System_AudioSilencer(), args, Helpers.SettingsType.Edit, Helpers.ActionBarType.HomeUp, R.string.system_audiosilencer_title, R.layout.prefs_system_audiosilencer);
return true;
}
});
break;
case "pref_key_system_cat_vibration":
findPreference("pref_key_system_vibration_apps").setEnabled(!Objects.equals(Helpers.prefs.getString("pref_key_system_vibration", "1"), "1"));


+ 251
- 0
app/src/main/java/name/mikanoshi/customiuizer/subs/System_AudioSilencer.java View File

@ -0,0 +1,251 @@
package name.mikanoshi.customiuizer.subs;
import android.annotation.SuppressLint;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewStub;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.Locale;
import java.util.Set;
import java.util.TimeZone;
import name.mikanoshi.customiuizer.R;
import name.mikanoshi.customiuizer.SubFragment;
import name.mikanoshi.customiuizer.mods.GlobalActions;
import name.mikanoshi.customiuizer.utils.Helpers;
import name.mikanoshi.customiuizer.utils.SoundData;
public class System_AudioSilencer extends SubFragment {
String key;
Handler handler;
ListView listView1;
ListView listView2;
SoundAdapter silencedAdapter;
SoundAdapter playedAdapter;
ArrayList<SoundData> silencedList = new ArrayList<SoundData>();
ArrayList<SoundData> playedList = new ArrayList<SoundData>();
BroadcastReceiver soundsReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
playedList = intent.getParcelableArrayListExtra("sounds");
if (playedList == null) playedList = new ArrayList<SoundData>();
playedAdapter.notifyDataSetChanged();
silencedAdapter.notifyDataSetChanged();
updateProgressBar(true);
}
};
SimpleDateFormat formatter = new SimpleDateFormat("H:mm:ss", Locale.getDefault());
private void loadSilenced() {
silencedList.clear();
Set<String> silencedSet = Helpers.prefs.getStringSet(key, new LinkedHashSet<String>());
if (silencedSet != null)
for (String data: silencedSet)
silencedList.add(SoundData.fromPref(data));
}
private void saveSilenced() {
Set<String> silencedSet = new LinkedHashSet<String>();
for (SoundData data: silencedList)
silencedSet.add(data.toPref());
Helpers.prefs.edit().putStringSet(key, silencedSet.size() == 0 ? null : silencedSet).apply();
silencedAdapter.notifyDataSetChanged();
playedAdapter.notifyDataSetChanged();
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Bundle args = getArguments();
key = args.getString("key");
loadSilenced();
silencedAdapter = new SoundAdapter(getContext(), true);
playedAdapter = new SoundAdapter(getContext(), false);
handler = new Handler();
formatter.setTimeZone(TimeZone.getDefault());
if (getView() != null) {
listView1 = getView().findViewById(android.R.id.text1);
listView2 = getView().findViewById(android.R.id.text2);
TextView cat1 = getView().findViewById(R.id.sounds_silenced);
TextView cat2 = getView().findViewById(R.id.sounds_played);
int resId = getResources().getIdentifier("preference_category_background", "drawable", "miui");
cat1.setBackgroundResource(resId);
cat2.setBackgroundResource(resId);
@SuppressLint("CutPasteId") ViewStub locationStub = getView().findViewById(R.id.refresh_list);
locationStub.setLayoutResource(R.layout.pref_item);
locationStub.inflate();
@SuppressLint("CutPasteId") View refresh = getView().findViewById(R.id.refresh_list);
((TextView)refresh.findViewById(android.R.id.title)).setText(R.string.system_audiosilencer_last_title);
((TextView)refresh.findViewById(android.R.id.summary)).setText(R.string.system_audiosilencer_last_summ);
Helpers.setMiuiPrefItem(refresh);
refresh.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
playedList.clear();
silencedAdapter.notifyDataSetChanged();
playedAdapter.notifyDataSetChanged();
updateProgressBar(false);
fetchPlayedSounds();
}
});
}
listView1.setAdapter(silencedAdapter);
listView1.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
SoundData data = silencedAdapter.getItem(position);
silencedList.remove(data);
saveSilenced();
}
});
listView2.setAdapter(playedAdapter);
listView2.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
SoundData data = playedAdapter.getItem(position);
silencedList.add(data);
saveSilenced();
}
});
updateProgressBar(false);
}
@Override
public void onCreate(Bundle savedInstanceState) {
this.padded = false;
super.onCreate(savedInstanceState);
}
Runnable getPlayedSounds = this::fetchPlayedSounds;
void fetchPlayedSounds() {
Intent intent = new Intent(GlobalActions.ACTION_PREFIX + "FetchPlayedSounds");
intent.setPackage("android");
getActivity().sendBroadcast(intent);
}
void updateProgressBar(boolean forceHide) {
if (getView() != null) getView().findViewById(R.id.progress_bar).setVisibility(forceHide || playedList.size() > 0 ? View.GONE : View.VISIBLE);
}
void registerReceivers() {
unregisterReceivers();
getActivity().registerReceiver(soundsReceiver, new IntentFilter(GlobalActions.EVENT_PREFIX + "FetchPlayedSoundsData"));
handler.postDelayed(getPlayedSounds, 1000);
}
void unregisterReceivers() {
try {
handler.removeCallbacks(getPlayedSounds);
getActivity().unregisterReceiver(soundsReceiver);
} catch (Throwable t) {}
}
@Override
public void onDestroy() {
unregisterReceivers();
super.onDestroy();
}
@Override
public void onPause() {
unregisterReceivers();
super.onPause();
}
@Override
public void onResume() {
super.onResume();
registerReceivers();
}
public class SoundAdapter extends BaseAdapter {
private final boolean isSelected;
private final LayoutInflater mInflater;
SoundAdapter(Context context, boolean selected) {
isSelected = selected;
mInflater = LayoutInflater.from(context);
}
public int getCount() {
if (isSelected)
return silencedList.size();
else
return playedList.size();
}
public SoundData getItem(int position) {
return isSelected ? silencedList.get(position) : playedList.get(position);
}
public long getItemId(int position) {
return position;
}
@Override
public boolean isEnabled(int position) {
return isSelected || !silencedList.contains(playedList.get(position));
}
public View getView(final int position, View convertView, ViewGroup parent) {
View row;
if (convertView != null) {
row = convertView;
} else {
row = mInflater.inflate(R.layout.pref_item_detailed, parent, false);
Helpers.setMiuiPrefItem(row);
}
TextView itemPackage = row.findViewById(android.R.id.title);
TextView itemUid = row.findViewById(android.R.id.summary);
TextView itemType = row.findViewById(android.R.id.text1);
TextView itemTime = row.findViewById(android.R.id.text2);
SoundData data = getItem(position);
itemPackage.setText(data.caller);
itemUid.setText(data.uid);
itemType.setText("file".equals(data.type) ? getResources().getString(R.string.type_file) : "resource".equals(data.type) ? getResources().getString(R.string.type_res) : "uri".equals(data.type) ? "URI" : "");
itemTime.setText(isSelected ? "" : formatter.format(data.time));
if (isEnabled(position)) {
row.setEnabled(true);
itemPackage.setTextColor(getResources().getColor(R.color.preference_primary_text_color, getActivity().getTheme()));
itemPackage.setAlpha(1.0f);
itemUid.setAlpha(1.0f);
itemType.setAlpha(1.0f);
itemTime.setAlpha(1.0f);
} else {
row.setEnabled(false);
itemPackage.setTextColor(getResources().getColor(R.color.preference_secondary_text_color, getActivity().getTheme()));
itemPackage.setAlpha(0.5f);
itemUid.setAlpha(0.5f);
itemType.setAlpha(0.5f);
itemTime.setAlpha(0.5f);
}
return row;
}
}
}

+ 8
- 4
app/src/main/java/name/mikanoshi/customiuizer/subs/WiFiList.java