diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index f086a1149..6c63102f7 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -113,9 +113,6 @@ dependencies {
implementation("androidx.work:work-runtime:2.9.0")
implementation("androidx.concurrent:concurrent-futures:1.1.0")
- // Palette
- implementation("androidx.palette:palette:1.0.0")
-
// Biometric Auth
implementation("androidx.biometric:biometric:1.1.0")
@@ -130,12 +127,6 @@ dependencies {
// ColorPicker
implementation("com.jaredrummler:colorpicker:1.1.0") //Color Picker Component for UI
- // ViewPager2
- implementation("androidx.viewpager2:viewpager2:1.0.0")
-
- // Circle Indicator
- implementation("me.relex:circleindicator:2.1.6")
-
// Lottie
implementation("com.airbnb.android:lottie:6.4.0")
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 37238a122..df08fd731 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -91,6 +91,11 @@
android:foregroundServiceType="location"
android:permission="android.permission.BIND_JOB_SERVICE" />
+
+
rootAllowedPacks;
+ private final boolean rootGranted;
+
+ private RootPoviderProxyIPC(Context context)
+ {
+ try {
+ Shell.setDefaultBuilder(Shell.Builder.create().setFlags(Shell.FLAG_MOUNT_MASTER));
+ }
+ catch (Throwable ignored){}
+ rootGranted = Shell.getShell().isRoot();
+
+ rootAllowedPacks = Arrays.asList(context.getResources().getStringArray(R.array.xposed_scope));
+ }
+
+ /** @noinspection RedundantThrows*/
+ @Override
+ public String[] runCommand(String command) throws RemoteException {
+ try {
+ ensureEnvironment();
+
+ List result = Shell.cmd(command).exec().getOut();
+ return result.toArray(new String[0]);
+ }
+ catch (Throwable t)
+ {
+ return new String[0];
+ }
+ }
+
+ private void ensureEnvironment() throws RemoteException {
+ if(!rootGranted)
+ {
+ throw new RemoteException("Root permission denied");
+ }
+
+ ensureSecurity(Binder.getCallingUid());
+ }
+
+ private void ensureSecurity(int uid) throws RemoteException {
+ for (String packageName : getPackageManager().getPackagesForUid(uid)) {
+ if(rootAllowedPacks.contains(packageName))
+ return;
+ }
+ throw new RemoteException("You do know you're not supposed to use this service. So...");
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/it/dhd/oxygencustomizer/xposed/XPLauncher.java b/app/src/main/java/it/dhd/oxygencustomizer/xposed/XPLauncher.java
index b7788635e..b23a9e62a 100644
--- a/app/src/main/java/it/dhd/oxygencustomizer/xposed/XPLauncher.java
+++ b/app/src/main/java/it/dhd/oxygencustomizer/xposed/XPLauncher.java
@@ -7,21 +7,32 @@
import static it.dhd.oxygencustomizer.BuildConfig.APPLICATION_ID;
import static it.dhd.oxygencustomizer.xposed.XPrefs.Xprefs;
import static it.dhd.oxygencustomizer.xposed.utils.BootLoopProtector.isBootLooped;
+import static it.dhd.oxygencustomizer.xposed.utils.SystemUtils.sleep;
import android.annotation.SuppressLint;
import android.app.Instrumentation;
+import android.app.Service;
+import android.content.ComponentName;
import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.IBinder;
+import android.os.RemoteException;
import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.Objects;
+import java.util.Queue;
import java.util.concurrent.CompletableFuture;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.callbacks.XC_LoadPackage;
import it.dhd.oxygencustomizer.BuildConfig;
+import it.dhd.oxygencustomizer.IRootProviderProxy;
import it.dhd.oxygencustomizer.utils.Constants;
import it.dhd.oxygencustomizer.xposed.utils.SystemUtils;
-public class XPLauncher {
+public class XPLauncher implements ServiceConnection {
public static boolean isChildProcess = false;
public static String processName = "";
@@ -29,6 +40,8 @@ public class XPLauncher {
public static ArrayList runningMods = new ArrayList<>();
public Context mContext = null;
+ private static IRootProviderProxy rootProxyIPC;
+ private static final Queue proxyQueue = new LinkedList<>();
@SuppressLint("StaticFieldLeak")
static XPLauncher instance;
@@ -106,6 +119,7 @@ private void onXPrefsReady(XC_LoadPackage.LoadPackageParam lpparam) {
}
private void loadModpacks(XC_LoadPackage.LoadPackageParam lpparam) {
+ forceConnectRootService();
for (Class extends XposedMods> mod : ModPacks.getMods(lpparam.packageName)) {
try {
XposedMods instance = mod.getConstructor(Context.class).newInstance(mContext);
@@ -141,4 +155,81 @@ private void waitForXprefsLoad(XC_LoadPackage.LoadPackageParam lpparam) {
onXPrefsReady(lpparam);
}
+
+ private void forceConnectRootService()
+ {
+ new Thread(() -> {
+ while(SystemUtils.UserManager() == null
+ || !SystemUtils.UserManager().isUserUnlocked()) //device is still CE encrypted
+ {
+ sleep(2000);
+ }
+ sleep(5000); //wait for the unlocked account to settle down a bit
+
+ while(rootProxyIPC == null)
+ {
+ connectRootService();
+ sleep(5000);
+ }
+ }).start();
+ }
+
+ private void connectRootService()
+ {
+ try {
+ Intent intent = new Intent();
+ intent.setComponent(new ComponentName(APPLICATION_ID, APPLICATION_ID + ".services.RootProviderProxy"));
+ mContext.bindService(intent, instance, Context.BIND_AUTO_CREATE | Context.BIND_ADJUST_WITH_ACTIVITY);
+ }
+ catch (Throwable t)
+ {
+ log(t);
+ }
+ }
+
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ rootProxyIPC = IRootProviderProxy.Stub.asInterface(service);
+ synchronized (proxyQueue)
+ {
+ while(!proxyQueue.isEmpty())
+ {
+ try
+ {
+ Objects.requireNonNull(proxyQueue.poll()).run(rootProxyIPC);
+ }
+ catch (Throwable ignored){}
+ }
+ }
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ rootProxyIPC = null;
+
+ forceConnectRootService();
+ }
+
+ public static void enqueueProxyCommand(ProxyRunnable runnable)
+ {
+ if(rootProxyIPC != null)
+ {
+ try {
+ runnable.run(rootProxyIPC);
+ } catch (RemoteException ignored) {}
+ }
+ else
+ {
+ synchronized (proxyQueue) {
+ proxyQueue.add(runnable);
+ }
+ instance.forceConnectRootService();
+ }
+ }
+
+ public interface ProxyRunnable
+ {
+ void run(IRootProviderProxy proxy) throws RemoteException;
+ }
+
}
diff --git a/app/src/main/java/it/dhd/oxygencustomizer/xposed/hooks/systemui/FeatureEnabler.java b/app/src/main/java/it/dhd/oxygencustomizer/xposed/hooks/systemui/FeatureEnabler.java
index a9fa4eea2..2dcd8aaa7 100644
--- a/app/src/main/java/it/dhd/oxygencustomizer/xposed/hooks/systemui/FeatureEnabler.java
+++ b/app/src/main/java/it/dhd/oxygencustomizer/xposed/hooks/systemui/FeatureEnabler.java
@@ -26,6 +26,7 @@
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.hardware.biometrics.BiometricManager;
+import android.os.RemoteException;
import android.view.MotionEvent;
import android.widget.ArrayAdapter;
import android.widget.ListView;
@@ -34,8 +35,10 @@
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.callbacks.XC_LoadPackage;
+import it.dhd.oxygencustomizer.IRootProviderProxy;
import it.dhd.oxygencustomizer.R;
import it.dhd.oxygencustomizer.utils.Constants;
+import it.dhd.oxygencustomizer.xposed.XPLauncher;
import it.dhd.oxygencustomizer.xposed.XposedMods;
import it.dhd.oxygencustomizer.xposed.utils.ShellUtils;
@@ -195,11 +198,11 @@ private void showDialog() throws Exception {
listView.setScrollContainer(false);
listView.setOnItemClickListener((parent, view, position, id) -> {
switch (position) {
- case 0 -> ShellUtils.execCommand("reboot recovery", true);
- case 1 -> ShellUtils.execCommand("reboot bootloader", true);
- case 2 -> ShellUtils.execCommand("reboot safemode", true);
- case 3 -> ShellUtils.execCommand("killall zygote", true);
- case 4 -> restartAllScope(new String[]{SYSTEM_UI});
+ case 0 -> XPLauncher.enqueueProxyCommand(proxy -> proxy.runCommand("reboot recovery"));//ShellUtils.execCommand("reboot recovery", true);
+ case 1 -> XPLauncher.enqueueProxyCommand(proxy -> proxy.runCommand("reboot bootloader"));//ShellUtils.execCommand("reboot bootloader", true);
+ case 2 -> XPLauncher.enqueueProxyCommand(proxy -> proxy.runCommand("reboot safemode"));//ShellUtils.execCommand("reboot safemode", true);
+ case 3 -> XPLauncher.enqueueProxyCommand(proxy -> proxy.runCommand("killall zygote"));//ShellUtils.execCommand("killall zygote", true);
+ case 4 -> XPLauncher.enqueueProxyCommand(proxy -> proxy.runCommand("killall " + SYSTEM_UI));//restartAllScope(new String[]{SYSTEM_UI});
}
});
diff --git a/app/src/main/java/it/dhd/oxygencustomizer/xposed/hooks/systemui/statusbar/BatteryStyleManager.java b/app/src/main/java/it/dhd/oxygencustomizer/xposed/hooks/systemui/statusbar/BatteryStyleManager.java
index e235095c5..c0e2f42ce 100644
--- a/app/src/main/java/it/dhd/oxygencustomizer/xposed/hooks/systemui/statusbar/BatteryStyleManager.java
+++ b/app/src/main/java/it/dhd/oxygencustomizer/xposed/hooks/systemui/statusbar/BatteryStyleManager.java
@@ -8,7 +8,10 @@
import static de.robv.android.xposed.XposedHelpers.findAndHookConstructor;
import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;
import static de.robv.android.xposed.XposedHelpers.findClass;
+import static de.robv.android.xposed.XposedHelpers.getAdditionalInstanceField;
import static de.robv.android.xposed.XposedHelpers.getObjectField;
+import static de.robv.android.xposed.XposedHelpers.setAdditionalInstanceField;
+import static de.robv.android.xposed.XposedHelpers.setObjectField;
import static it.dhd.oxygencustomizer.utils.Constants.Preferences.BatteryPrefs.BATTERY_STYLE_CIRCLE;
import static it.dhd.oxygencustomizer.utils.Constants.Preferences.BatteryPrefs.BATTERY_STYLE_CUSTOM_LANDSCAPE;
import static it.dhd.oxygencustomizer.utils.Constants.Preferences.BatteryPrefs.BATTERY_STYLE_CUSTOM_RLANDSCAPE;
@@ -78,6 +81,7 @@
import static it.dhd.oxygencustomizer.xposed.hooks.systemui.BatteryDataProvider.isPowerSaving;
import static it.dhd.oxygencustomizer.xposed.hooks.systemui.OpUtils.getChargingColor;
import static it.dhd.oxygencustomizer.xposed.utils.ViewHelper.dp2px;
+import static it.dhd.oxygencustomizer.xposed.utils.ViewHelper.setMargins;
import android.content.Context;
import android.content.res.Resources;
@@ -89,11 +93,13 @@
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.res.ResourcesCompat;
@@ -138,6 +144,7 @@
import it.dhd.oxygencustomizer.xposed.batterystyles.RLandscapeBatteryColorOS;
import it.dhd.oxygencustomizer.xposed.batterystyles.RLandscapeBatteryStyleA;
import it.dhd.oxygencustomizer.xposed.batterystyles.RLandscapeBatteryStyleB;
+import it.dhd.oxygencustomizer.xposed.hooks.systemui.BatteryDataProvider;
import it.dhd.oxygencustomizer.xposed.utils.ShellUtils;
public class BatteryStyleManager extends XposedMods {
@@ -149,6 +156,7 @@ public class BatteryStyleManager extends XposedMods {
private static final ArrayList batteryViews = new ArrayList<>();
private static final int BatteryIconOpacity = 100;
private static int BatteryStyle = 0;
+ public static int mBatteryStyle = 0;
private static boolean mShowPercentInside = true;
private static boolean mHidePercentage = false;
private static boolean mHideBattery = false;
@@ -173,15 +181,14 @@ public class BatteryStyleManager extends XposedMods {
private int mCustomPowerSaveFillColor = Color.BLACK;
private int mCustomFastChargingColor = Color.BLACK;
private boolean mSwapPercentage = false;
- private boolean mChargingIconSwitch = false;
+ private static boolean mChargingIconSwitch = false;
private int mChargingIconStyle = 0;
private int mChargingIconML = 1;
private int mChargingIconMR = 0;
private int mChargingIconWH = 14;
- private boolean mIsChargingImpl = false;
- private boolean mIsCharging = false;
+ private static boolean mIsPowerSaving = false;
+ private static boolean mIsCharging = false;
private ImageView mStockChargingIcon = null, mBatteryIcon = null;
- private ImageView mBatteryOOS13 = null;
private Object BatteryControllerImpl = null;
private boolean updating = false;
private boolean customizePercSize = false;
@@ -246,6 +253,29 @@ public void updatePrefs(String... Key) {
customizePercSize = Xprefs.getBoolean(STOCK_CUSTOMIZE_PERCENTAGE_SIZE, false);
mBatteryPercSize = Xprefs.getSliderInt(STOCK_PERCENTAGE_SIZE, 12);
+ if (mBatteryStyle != BatteryStyle && !oos13) {
+ mBatteryStyle = BatteryStyle;
+ for (View view : batteryViews) //destroy old drawables and make new ones :D
+ {
+
+ ImageView batteryIcon = null, chargingIcon = null;
+ TextView batteryOutPercentage = null, batteryInPercentage = null;
+ if (view instanceof LinearLayout) {
+ try {
+ batteryIcon = view.findViewById(mContext.getResources().getIdentifier("battery_icon_view", "id", mContext.getPackageName()));
+ } catch (Throwable ignored) {
+ }
+ }
+
+ if (CustomBatteryEnabled && batteryIcon != null) {
+ BatteryDrawable newDrawable = getNewBatteryDrawable(mContext);
+ batteryIcon.setImageDrawable(newDrawable);
+ setAdditionalInstanceField(view, "mBatteryDrawable", newDrawable);
+ }
+ }
+ }
+
+ /*
if (Key.length > 0 && (Key[0].equals(CUSTOMIZE_BATTERY_ICON) ||
Key[0].equals(CUSTOM_BATTERY_STYLE) ||
Key[0].equals(CUSTOM_BATTERY_HIDE_PERCENTAGE) ||
@@ -272,7 +302,9 @@ public void updatePrefs(String... Key) {
Key[0].equals(STOCK_PERCENTAGE_SIZE)
)) {
notifyUpdate();
- }
+ }*/
+
+ if (!oos13) refreshAllBatteryIcons();
}
@Override
@@ -282,17 +314,61 @@ public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Th
if (Build.VERSION.SDK_INT >= 34) {
hookBattery(lpparam); // OOS 14
} else {
- if (mBatteryOOS13 == null) {
- mBatteryOOS13 = new ImageView(mContext);
- LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT);
- mBatteryOOS13.setLayoutParams(lp);
- }
hookBattery13(lpparam); // OOS 13
}
}
private void hookBattery(XC_LoadPackage.LoadPackageParam lpparam) {
+
+ BatteryDataProvider.registerInfoCallback(this::refreshAllBatteryIcons);
+
+ final View.OnAttachStateChangeListener listener = new View.OnAttachStateChangeListener() {
+ @Override
+ public void onViewAttachedToWindow(@NonNull View v) {
+ if (v instanceof LinearLayout batteryMeter) {
+ batteryViews.add(batteryMeter);
+ }
+ }
+
+ @Override
+ public void onViewDetachedFromWindow(@NonNull View v) {
+ batteryViews.remove(v);
+ }
+ };
+
+ Class> StatBatteryMeterView = findClass("com.oplus.systemui.statusbar.pipeline.battery.ui.view.StatBatteryMeterView", lpparam.classLoader);
+ hookAllConstructors(StatBatteryMeterView, new XC_MethodHook() {
+ @Override
+ protected void afterHookedMethod(MethodHookParam param) throws Throwable {
+ ((View) param.thisObject).addOnAttachStateChangeListener(listener);
+
+ if (!CustomBatteryEnabled) return;
+
+ BatteryDrawable mBatteryDrawable = getNewBatteryDrawable(mContext);
+ setAdditionalInstanceField(param.thisObject, "mBatteryDrawable", mBatteryDrawable);
+
+ }
+ });
+ findAndHookMethod(StatBatteryMeterView, "onFinishInflate", new XC_MethodHook() {
+ @Override
+ protected void afterHookedMethod(MethodHookParam param) throws Throwable {
+ //((View) param.thisObject).addOnAttachStateChangeListener(listener);
+
+ if (!CustomBatteryEnabled) return;
+
+ LinearLayout batteryMeterView = (LinearLayout) param.thisObject;
+
+ ImageView mBatteryIconView = batteryMeterView.findViewById(mContext.getResources().getIdentifier("battery_icon_view", "id", mContext.getPackageName()));
+
+ BatteryDrawable mBatteryDrawable = getNewBatteryDrawable(mContext);
+ setAdditionalInstanceField(param.thisObject, "mBatteryDrawable", mBatteryDrawable);
+
+ mBatteryIconView.setImageDrawable(mBatteryDrawable);
+ }
+ });
+
+
Class> BatteryIconColor = findClass("com.oplus.systemui.statusbar.pipeline.battery.ui.model.BatteryIconColor", lpparam.classLoader);
findAndHookConstructor(BatteryIconColor,
@@ -307,29 +383,11 @@ protected void afterHookedMethod(MethodHookParam param) throws Throwable {
this.foregroundColor = i2;
this.backgroundColor = i3;
*/
+ if (!CustomBatteryEnabled) return;
singleToneColor = (int) param.args[0];
frameColor = (int) param.args[1];
backgroundColor = (int) param.args[2];
- if (mBatteryIcon != null) {
- if (mBatteryIcon.getDrawable() instanceof BatteryDrawable mBatteryDrawable) {
- mBatteryDrawable.setColors(frameColor, backgroundColor, singleToneColor);
- mBatteryDrawable.customizeBatteryDrawable(
- mBatteryLayoutReverse,
- mScaledPerimeterAlpha,
- mScaledFillAlpha,
- mCustomBlendColor,
- mRainbowFillColor,
- mCustomFillColor,
- mCustomFillGradColor,
- mCustomBlendColor ? mCustomChargingColor : getChargingColor(mCustomChargingColor),
- mCustomBlendColor ? mCustomFastChargingColor : getChargingColor(mCustomFastChargingColor),
- mCustomPowerSaveColor,
- mCustomPowerSaveFillColor,
- mChargingIconSwitch
- );
- mBatteryIcon.setImageDrawable(mBatteryDrawable);
- }
- }
+ updateIconsColor();
}
});
@@ -345,6 +403,11 @@ protected void afterHookedMethod(MethodHookParam param) throws Throwable {
hookAllMethods(BatteryViewBinder, "bind$initView", new XC_MethodHook() {
+ @Override
+ protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
+ //if (CustomBatteryEnabled) param.setResult(null);
+ }
+
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
/*
@@ -361,23 +424,27 @@ protected void afterHookedMethod(MethodHookParam param) throws Throwable {
8 StatBatteryIcon statBatteryIcon) {
*/
+ refreshAllBatteryIcons();
+
// No need to call BatteryDataProvider or BroadcastReceiver
// since battery view is updated automatically
- mIsCharging = isCharging();
- boolean isCharging = false;
-
- batteryPercentInView = (TextView) param.args[0];
+ /*batteryPercentInView = (TextView) param.args[0];
batteryPercentOutView = (TextView) param.args[1];
Object statBatteryIcon = param.args[8];
// Fix Charging if Battery Data Provider is not ready
if (statBatteryIcon != null) {
try {
- isCharging = (boolean) callMethod(statBatteryIcon, "getCharging");
+ mIsCharging = (boolean) callMethod(statBatteryIcon, "getCharging");
+ } catch (Throwable t) {
+ mIsCharging = isCharging();
+ }
+ try {
+ mIsPowerSaving = (boolean) callMethod(statBatteryIcon, "getSaveMode");
} catch (Throwable t) {
- isCharging = mIsCharging;
+ mIsPowerSaving = isPowerSaving();
}
}
@@ -443,7 +510,7 @@ protected void afterHookedMethod(MethodHookParam param) throws Throwable {
if (mChargingIconSwitch) {
mStockChargingIcon = (ImageView) param.args[7];
- if (isCharging) {
+ if (mIsCharging) {
mStockChargingIcon.setVisibility(View.VISIBLE);
if (mChargingIconSwitch) {
mStockChargingIcon.setImageDrawable(getNewChargingIcon());
@@ -459,14 +526,142 @@ protected void afterHookedMethod(MethodHookParam param) throws Throwable {
mStockChargingIcon.setVisibility(View.GONE);
}
}
+ updateAllIcons();*/
}
});
}
+ private void refreshAllBatteryIcons() {
+ for (View view : batteryViews) {
+ updateBatteryViewValues(view);
+ }
+ }
+
+ private void updateBatteryViewValues(View view)
+ {
+ TextView batteryOutPercentage = null;
+ try {
+ batteryOutPercentage = view.findViewById(mContext.getResources().getIdentifier("battery_percentage_view", "id", mContext.getPackageName()));
+ } catch (Throwable ignored) {}
+ if (batteryOutPercentage != null && batteryOutPercentage.getVisibility() == View.VISIBLE) {
+ batteryOutPercentage.setTextSize(TypedValue.COMPLEX_UNIT_SP, customizePercSize ? mBatteryPercSize : 12);
+ }
+ if (!CustomBatteryEnabled) return;
+ //setPercentViewColor(view, forcePercentageColor);
+ ImageView batteryIcon = null, chargingIcon = null;
+ TextView batteryInPercentage = null;
+ if (view instanceof LinearLayout) {
+ try {
+ batteryIcon = view.findViewById(mContext.getResources().getIdentifier("battery_icon_view", "id", mContext.getPackageName()));
+ } catch (Throwable ignored) {}
+ try {
+ chargingIcon = view.findViewById(mContext.getResources().getIdentifier("battery_dash_charge_view", "id", mContext.getPackageName()));
+ } catch (Throwable ignored) {}
+ try {
+ batteryInPercentage = view.findViewById(mContext.getResources().getIdentifier("battery_text", "id", mContext.getPackageName()));
+ batteryInPercentage.setVisibility(View.GONE);
+ } catch (Throwable ignored) {}
+ for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
+ View child = ((ViewGroup) view).getChildAt(i);
+ if (child instanceof FrameLayout) {
+ child.setVisibility(View.GONE);
+ } else {
+ if (child != batteryIcon && child != batteryOutPercentage && child != batteryInPercentage) {
+ child.setVisibility(View.GONE);
+ }
+ }
+ }
+ }
+ if (CustomBatteryEnabled && batteryIcon != null) {
+ scaleBatteryMeterViews(batteryIcon);
+ updateBatteryRotation(batteryIcon);
+ updateFlipper(batteryIcon.getParent());
+ mIsCharging = isCharging();
+ mIsPowerSaving = isPowerSaving();
+ batteryIcon.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
+ if (batteryOutPercentage != null) {
+ if (mHidePercentage) {
+ batteryOutPercentage.setVisibility(View.GONE);
+ } else {
+ batteryOutPercentage.setVisibility(View.VISIBLE);
+ }
+ }
+ try {
+ BatteryDrawable drawable = (BatteryDrawable) getAdditionalInstanceField(view, "mBatteryDrawable");
+ drawable.setChargingEnabled(mIsCharging, isFastCharging());
+ drawable.setPowerSavingEnabled(isPowerSaving());
+ drawable.setShowPercentEnabled(mShowPercentInside);
+ drawable.setAlpha(Math.round(BatteryIconOpacity * 2.55f));
+ drawable.setColors(frameColor, backgroundColor, singleToneColor);
+ drawable.customizeBatteryDrawable(
+ mBatteryLayoutReverse,
+ mScaledPerimeterAlpha,
+ mScaledFillAlpha,
+ mCustomBlendColor,
+ mRainbowFillColor,
+ mCustomFillColor,
+ mCustomFillGradColor,
+ mCustomBlendColor ? mCustomChargingColor : getChargingColor(mCustomChargingColor),
+ mCustomBlendColor ? mCustomFastChargingColor : getChargingColor(mCustomFastChargingColor),
+ mCustomPowerSaveColor,
+ mCustomPowerSaveFillColor,
+ mChargingIconSwitch
+ );
+ drawable.setBatteryLevel(getCurrentLevel());
+ drawable.invalidateSelf();
+ } catch (Throwable ignored) {} //it's probably the default battery. no action needed
+ }
+
+
+ if (mChargingIconSwitch && chargingIcon != null) {
+ if (mIsCharging) {
+ chargingIcon.setImageDrawable(getNewChargingIcon());
+ chargingIcon.setVisibility(View.VISIBLE);
+ int size = dp2px(mContext, mChargingIconWH);
+ chargingIcon.setLayoutParams(new LinearLayout.LayoutParams(size, size));
+ setMargins(chargingIcon, mContext, mChargingIconML, 0, mChargingIconMR, 0);
+ }
+ chargingIcon.setVisibility(mIsCharging ? View.VISIBLE : View.GONE);
+ }
+ }
+
+ private void updateIconsColor() {
+ if (batteryViews.isEmpty()) return;
+ for (View v : batteryViews) {
+ if (v instanceof ImageView) {
+ Drawable drawable = ((ImageView) v).getDrawable();
+ if (drawable instanceof BatteryDrawable) {
+ ((BatteryDrawable) drawable).setColors(frameColor, backgroundColor, singleToneColor);
+ }
+ drawable.invalidateSelf();
+ } else if (v instanceof LinearLayout) {
+ if (oos13) return;
+ BatteryDrawable mBatteryDrawable = (BatteryDrawable) getAdditionalInstanceField(v, "mBatteryDrawable");
+ mBatteryDrawable.setColors(frameColor, backgroundColor, singleToneColor);
+ mBatteryDrawable.invalidateSelf();
+ }
+ }
+ }
+
+ private void updateAllIcons() {
+ if (batteryViews.isEmpty()) return;
+ for (View v : batteryViews) {
+ if (v instanceof ImageView) {
+ Drawable drawable = ((ImageView) v).getDrawable();
+ if (drawable instanceof BatteryDrawable) {
+ ((BatteryDrawable) drawable).setPowerSavingEnabled(mIsPowerSaving);
+ ((BatteryDrawable) drawable).setChargingEnabled(mIsCharging, isFastCharging());
+ drawable.invalidateSelf();
+ }
+ }
+ }
+ }
+
private void hookBattery13(XC_LoadPackage.LoadPackageParam lpparam) {
oos13 = true;
Class> TwoBatteryMeterDrawable = findClass("com.oplusos.systemui.statusbar.widget.TwoBatteryMeterDrawable", lpparam.classLoader);
- findAndHookMethod(TwoBatteryMeterDrawable, "setColors",
+ Class> StatBatteryMeterView = findClass("com.oplusos.systemui.statusbar.widget.StatBatteryMeterView", lpparam.classLoader);
+ findAndHookMethod(StatBatteryMeterView, "updateColors",
int.class,
int.class,
int.class, new XC_MethodHook() {
@@ -492,14 +687,32 @@ public void setColors(int i, int i2) {
}
*/
- backgroundColor = (int) param.args[0];
- frameColor = (int) param.args[1];
- singleToneColor = (int) param.args[1];
-
+ backgroundColor = (int) param.args[1];
+ frameColor = (int) param.args[0];
+ singleToneColor = (int) param.args[2];
+ updateIconsColor();
}
});
+ final View.OnAttachStateChangeListener listener = new View.OnAttachStateChangeListener() {
+ @Override
+ public void onViewAttachedToWindow(@NonNull View v) {
+ if (v instanceof ImageView batteryIconView) {
+ batteryViews.add(batteryIconView);
+ }
+ }
- Class> StatBatteryMeterView = findClass("com.oplusos.systemui.statusbar.widget.StatBatteryMeterView", lpparam.classLoader);
+ @Override
+ public void onViewDetachedFromWindow(View v) {
+ batteryViews.remove(v);
+ }
+ };
+ findAndHookMethod(StatBatteryMeterView, "initViews", Context.class, new XC_MethodHook() {
+ @Override
+ protected void afterHookedMethod(MethodHookParam param) throws Throwable {
+ View v = (View) getObjectField(param.thisObject, "mBatteryIconView");
+ v.addOnAttachStateChangeListener(listener);
+ }
+ });
findAndHookMethod(StatBatteryMeterView, "onBatteryLevelChanged",
int.class,
boolean.class,
@@ -507,8 +720,6 @@ public void setColors(int i, int i2) {
new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
- mBatteryIcon = (ImageView) getObjectField(param.thisObject, "mBatteryIconView");
- batteryPercentOutView = (TextView) getObjectField(param.thisObject, "batteryPercentText");
/*
public void onBatteryLevelChanged(int i, boolean z, boolean z2) {
@@ -519,9 +730,13 @@ public void onBatteryLevelChanged(int i, boolean z, boolean z2) {
twoBatteryMeterDrawable.setBatteryLevel(i);
}
*/
-
- int batteryLevel = (int) param.args[0];
+ //batteryLevel = (int) param.args[0];
+ log(TAG + "onBatteryLevelChanged");
mIsCharging = (boolean) param.args[2];
+ mBatteryIcon = (ImageView) getObjectField(param.thisObject, "mBatteryIconView");
+ batteryPercentOutView = (TextView) getObjectField(param.thisObject, "batteryPercentText");
+ ImageView batteryCharge = (ImageView) getObjectField(param.thisObject, "batteryCharge");
+ int batteryLevel = (int) param.args[0];//getCurrentLevel();
if (CustomBatteryEnabled && mBatteryIcon != null) {
if (mHidePercentage)
@@ -552,25 +767,35 @@ public void onBatteryLevelChanged(int i, boolean z, boolean z2) {
mCustomPowerSaveFillColor,
mChargingIconSwitch
);
- mBatteryIcon.setScaleType(ImageView.ScaleType.FIT_XY);
- mBatteryIcon.setLayerType(View.LAYER_TYPE_NONE, null);
+ mBatteryIcon.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
+ scaleBatteryMeterViews(mBatteryIcon);
+ updateBatteryRotation(mBatteryIcon);
+ updateFlipper(mBatteryIcon.getParent());
mBatteryIcon.setImageDrawable(mBatteryDrawable);
}
- scaleBatteryMeterViews(mBatteryIcon);
- updateBatteryRotation(mBatteryIcon);
- updateFlipper(mBatteryIcon.getParent());
} else {
if (customizePercSize) {
if (batteryPercentOutView != null && batteryPercentOutView.getVisibility() == View.VISIBLE)
batteryPercentOutView.setTextSize(TypedValue.COMPLEX_UNIT_SP, mBatteryPercSize);
}
}
- }
- });
- findAndHookMethod(StatBatteryMeterView, "initViews", Context.class, new XC_MethodHook() {
- @Override
- protected void afterHookedMethod(MethodHookParam param) throws Throwable {
+
+ if (mChargingIconSwitch && batteryCharge != null) {
+ if (mIsCharging) {
+ batteryCharge.setVisibility(View.VISIBLE);
+ batteryCharge.setImageDrawable(getNewChargingIcon());
+ int left = dp2px(mContext, mChargingIconML);
+ int right = dp2px(mContext, mChargingIconMR);
+ int size = dp2px(mContext, mChargingIconWH);
+
+ LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(size, size);
+ lp.setMargins(left, 0, right, mContext.getResources().getDimensionPixelSize(mContext.getResources().getIdentifier("battery_margin_bottom", "dimen", mContext.getPackageName())));
+ batteryCharge.setLayoutParams(lp);
+ } else {
+ batteryCharge.setVisibility(View.GONE);
+ }
+ }
}
});
@@ -694,13 +919,14 @@ public static void scaleBatteryMeterViews(@Nullable ImageView mBatteryIconView)
int batteryWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mBatteryScaleWidth, mBatteryIconView.getContext().getResources().getDisplayMetrics());
int batteryHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mBatteryScaleHeight, mBatteryIconView.getContext().getResources().getDisplayMetrics());
- LinearLayout.LayoutParams scaledLayoutParams;
- if (!oos13) scaledLayoutParams = (LinearLayout.LayoutParams) mBatteryIconView.getLayoutParams();
- else scaledLayoutParams = new LinearLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT);
- scaledLayoutParams.width = (int) (batteryWidth * iconScaleFactor);
- scaledLayoutParams.height = (int) (batteryHeight * iconScaleFactor);
- scaledLayoutParams.setMargins(mBatteryStockMarginLeft, 0, mBatteryStockMarginRight, context.getResources().getDimensionPixelOffset(context.getResources().getIdentifier("battery_margin_bottom", "dimen", context.getPackageName())));
-
+ LinearLayout.LayoutParams scaledLayoutParams = (LinearLayout.LayoutParams) mBatteryIconView.getLayoutParams();
+ if (!oos13) {
+ scaledLayoutParams.width = (int) (batteryWidth * iconScaleFactor);
+ scaledLayoutParams.height = (int) (batteryHeight * iconScaleFactor);
+ } else {
+ scaledLayoutParams.width = batteryWidth;
+ scaledLayoutParams.height = batteryHeight;
+ }
mBatteryIconView.setLayoutParams(scaledLayoutParams);
mBatteryIconView.setVisibility(mHideBattery ? View.GONE : View.VISIBLE);
mBatteryIconView.requestLayout();