导航菜单

页面标题

页面副标题

xDrip+ v04633772025.07.16 - UiBasedCollector.java 源代码

正在查看: xDrip+ v04633772025.07.16 应用的 UiBasedCollector.java JAVA 源代码文件

本页面展示 JAVA 反编译生成的源代码文件,支持语法高亮显示。 仅供安全研究与技术分析使用,严禁用于任何非法用途。请遵守相关法律法规。


package com.eveningoutpost.dexdrip.services;

import android.app.Activity;
import android.app.Notification;
import android.content.ComponentName;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.provider.Settings;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.text.TextUtils;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RemoteViews;
import android.widget.TextView;
import com.eveningoutpost.dexdrip.BestGlucose;
import com.eveningoutpost.dexdrip.alert.Persist$DoubleTimeout;
import com.eveningoutpost.dexdrip.cgm.dex.BlueTails;
import com.eveningoutpost.dexdrip.cgm.dex.ClassifierAction;
import com.eveningoutpost.dexdrip.models.BgReading;
import com.eveningoutpost.dexdrip.models.JoH;
import com.eveningoutpost.dexdrip.models.Sensor;
import com.eveningoutpost.dexdrip.models.UserError;
import com.eveningoutpost.dexdrip.utilitymodels.PersistentStore;
import com.eveningoutpost.dexdrip.utilitymodels.Unitized;
import com.eveningoutpost.dexdrip.utils.DexCollectionType;
import com.eveningoutpost.dexdrip.xdrip;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class UiBasedCollector extends NotificationListenerService {
    private static final String TAG = "UiBasedCollector";
    private static final HashSet<String> coOptedPackages;
    private static final HashSet<String> coOptedPackagesAll;
    private static final HashSet<String> companionAppIoBPackages;
    private static final HashSet<Pattern> companionAppIoBRegexes;
    private static boolean debug;
    private static final Persist$DoubleTimeout iob_store = new Persist$DoubleTimeout("COMPANION_APP_IOB_VALUE", 300000);
    String lastPackage;

    @Override
    public void onNotificationRemoved(StatusBarNotification statusBarNotification) {
    }

    static {
        HashSet<String> hashSet = new HashSet<>();
        coOptedPackages = hashSet;
        HashSet<String> hashSet2 = new HashSet<>();
        coOptedPackagesAll = hashSet2;
        HashSet<String> hashSet3 = new HashSet<>();
        companionAppIoBPackages = hashSet3;
        HashSet<Pattern> hashSet4 = new HashSet<>();
        companionAppIoBRegexes = hashSet4;
        debug = false;
        hashSet.add("com.dexcom.g6");
        hashSet.add("com.dexcom.g6.region1.mmol");
        hashSet.add("com.dexcom.g6.region2.mgdl");
        hashSet.add("com.dexcom.g6.region3.mgdl");
        hashSet.add("com.dexcom.g6.region4.mmol");
        hashSet.add("com.dexcom.g6.region5.mmol");
        hashSet.add("com.dexcom.g6.region6.mgdl");
        hashSet.add("com.dexcom.g6.region7.mmol");
        hashSet.add("com.dexcom.g6.region8.mmol");
        hashSet.add("com.dexcom.g6.region9.mgdl");
        hashSet.add("com.dexcom.g6.region10.mgdl");
        hashSet.add("com.dexcom.g6.region11.mmol");
        hashSet.add("com.dexcom.dexcomone");
        hashSet.add("com.dexcom.stelo");
        hashSet.add("com.dexcom.g7");
        hashSet.add("com.dexcom.d1plus");
        hashSet.add("com.camdiab.fx_alert.mmoll");
        hashSet.add("com.camdiab.fx_alert.mgdl");
        hashSet.add("com.camdiab.fx_alert.hx.mmoll");
        hashSet.add("com.camdiab.fx_alert.hx.mgdl");
        hashSet.add("com.camdiab.fx_alert.mmoll.ca");
        hashSet.add("com.medtronic.diabetes.guardian");
        hashSet.add("com.medtronic.diabetes.guardianconnect");
        hashSet.add("com.medtronic.diabetes.guardianconnect.us");
        hashSet.add("com.medtronic.diabetes.minimedmobile.eu");
        hashSet.add("com.medtronic.diabetes.minimedmobile.us");
        hashSet.add("com.medtronic.diabetes.simplera.eu");
        hashSet.add("com.senseonics.gen12androidapp");
        hashSet.add("com.senseonics.androidapp");
        hashSet.add("com.microtech.aidexx.mgdl");
        hashSet.add("com.ottai.seas");
        hashSet.add("com.microtech.aidexx");
        hashSet.add("com.ottai.tag");
        hashSet.add("com.senseonics.eversense365.us");
        hashSet.add("com.kakaohealthcare.pasta");
        hashSet.add("com.sinocare.cgm.ce");
        hashSet.add("com.sinocare.ican.health.ce");
        hashSet2.add("com.dexcom.dexcomone");
        hashSet2.add("com.dexcom.d1plus");
        hashSet2.add("com.dexcom.stelo");
        hashSet2.add("com.medtronic.diabetes.guardian");
        hashSet2.add("com.medtronic.diabetes.simplera.eu");
        hashSet2.add("com.senseonics.gen12androidapp");
        hashSet2.add("com.senseonics.androidapp");
        hashSet2.add("com.microtech.aidexx.mgdl");
        hashSet2.add("com.ottai.seas");
        hashSet2.add("com.microtech.aidexx");
        hashSet2.add("com.ottai.tag");
        hashSet2.add("com.senseonics.eversense365.us");
        hashSet2.add("com.kakaohealthcare.pasta");
        hashSet2.add("com.sinocare.cgm.ce");
        hashSet2.add("com.sinocare.ican.health.ce");
        hashSet3.add("com.insulet.myblue.pdm");
        hashSet4.add(Pattern.compile("IOB: ([\\d\\.,]+) U"));
    }

    @Override
    public void onNotificationPosted(StatusBarNotification statusBarNotification) {
        String packageName = statusBarNotification.getPackageName();
        if (coOptedPackages.contains(packageName)) {
            if (DexCollectionType.getDexCollectionType() == DexCollectionType.UiBased) {
                UserError.Log.d(TAG, "Notification from: " + packageName);
                if (statusBarNotification.isOngoing() || coOptedPackagesAll.contains(packageName)) {
                    this.lastPackage = packageName;
                    processNotification(statusBarNotification.getNotification());
                    BlueTails.immortality();
                }
            } else if (JoH.pratelimit("warn-notification-access", 7200)) {
                UserError.Log.wtf(TAG, "Receiving notifications that we are not enabled to process: " + packageName);
            }
        }
        if (companionAppIoBPackages.contains(packageName)) {
            processCompanionAppIoBNotification(statusBarNotification.getNotification());
        }
    }

    private void processCompanionAppIoBNotification(Notification notification) {
        if (notification == null) {
            UserError.Log.e(TAG, "Null notification");
            return;
        }
        RemoteViews remoteViews = notification.contentView;
        if (remoteViews != null) {
            processCompanionAppIoBNotificationCV(remoteViews);
        } else {
            UserError.Log.e(TAG, "Content is empty");
        }
    }

    private void processCompanionAppIoBNotificationCV(RemoteViews remoteViews) {
        if (remoteViews == null) {
            return;
        }
        Double d = null;
        ViewGroup viewGroup = (ViewGroup) remoteViews.apply(this, null).getRootView();
        ArrayList arrayList = new ArrayList();
        getTextViews(arrayList, viewGroup);
        if (debug) {
            UserError.Log.d(TAG, "Text views: " + arrayList.size());
        }
        try {
            Iterator it = arrayList.iterator();
            while (it.hasNext()) {
                TextView textView = (TextView) it.next();
                String charSequence = textView.getText() != null ? textView.getText().toString() : "";
                String charSequence2 = textView.getContentDescription() != null ? textView.getContentDescription().toString() : "";
                if (debug) {
                    UserError.Log.d(TAG, "Examining: >" + charSequence + "< : >" + charSequence2 + "<");
                }
                d = parseIoB(charSequence);
                if (d != null) {
                    break;
                }
            }
            if (d != null) {
                if (debug) {
                    UserError.Log.d(TAG, "Inserting new IoB value: " + d);
                }
                iob_store.set(d);
            }
        } catch (Exception e) {
            UserError.Log.e(TAG, "exception in processCompanionAppIoBNotificationCV: " + e);
        }
        arrayList.clear();
    }

    Double parseIoB(String str) {
        Iterator<Pattern> it = companionAppIoBRegexes.iterator();
        while (it.hasNext()) {
            Matcher matcher = it.next().matcher(str);
            if (matcher.find()) {
                return Double.valueOf(JoH.tolerantParseDouble(matcher.group(1)));
            }
        }
        return null;
    }

    public static Double getCurrentIoB() {
        return iob_store.get();
    }

    @Override
    public IBinder onBind(Intent intent) {
        return super.onBind(intent);
    }

    private void processNotification(Notification notification) {
        int tryExtractString;
        String channelId;
        if (notification == null) {
            UserError.Log.e(TAG, "Null notification");
            return;
        }
        Bundle bundle = notification.extras;
        String str = TAG;
        JoH.dumpBundle(bundle, str);
        if (notification.contentView != null) {
            if (Build.VERSION.SDK_INT >= 26) {
                channelId = notification.getChannelId();
                UserError.Log.d(str, "Channel ID: " + channelId);
            }
            processRemote(notification.contentView);
            return;
        }
        Bundle bundle2 = notification.extras;
        if (bundle2 != null) {
            String string = bundle2.getString("android.title");
            if (isValidString(string) && (tryExtractString = tryExtractString(string)) > 0) {
                handleNewValue(tryExtractString);
                return;
            }
        }
        UserError.Log.e(str, "Content is empty");
    }

    private boolean isValidString(String str) {
        return (str == null || str.trim().isEmpty()) ? false : true;
    }

    String filterString(String str) {
        String str2 = this.lastPackage;
        if (str2 == null) {
            return str;
        }
        str2.hashCode();
        return basicFilterString(arrowFilterString(str)).trim();
    }

    String basicFilterString(String str) {
        return str.replace(" ", " ").replace("\u2060", "").replace("\\", "/").replace("mmol/L", "").replace("mmol/l", "").replace("mg/dL", "").replace("mg/dl", "").replace("≤", "").replace("≥", "");
    }

    String arrowFilterString(String str) {
        return filterUnicodeRange(filterUnicodeRange(filterUnicodeRange(filterUnicodeRange(str, (char) 8592, (char) 8703), (char) 9984, (char) 10175), (char) 10496, (char) 10623), (char) 11008, (char) 11263);
    }

    public String filterUnicodeRange(String str, char c, char c2) {
        if (c > c2) {
            throw new RuntimeException("bottom and top of character range invalid");
        }
        StringBuilder sb = new StringBuilder(str.length());
        for (char c3 : str.toCharArray()) {
            if (c3 < c || c3 > c2) {
                sb.append(c3);
            }
        }
        return sb.toString();
    }

    private boolean processRemote(RemoteViews remoteViews) {
        if (remoteViews == null) {
            return false;
        }
        ViewGroup viewGroup = (ViewGroup) remoteViews.apply(this, null).getRootView();
        ArrayList arrayList = new ArrayList();
        getTextViews(arrayList, viewGroup);
        UserError.Log.d(TAG, "Text views: " + arrayList.size());
        Iterator it = arrayList.iterator();
        int i = 0;
        int i2 = 0;
        while (it.hasNext()) {
            TextView textView = (TextView) it.next();
            try {
                String charSequence = textView.getText() != null ? textView.getText().toString() : "";
                String charSequence2 = textView.getContentDescription() != null ? textView.getContentDescription().toString() : "";
                UserError.Log.d(TAG, "Examining: >" + charSequence + "< : >" + charSequence2 + "<");
                int tryExtractString = tryExtractString(charSequence);
                if (tryExtractString > 0) {
                    i++;
                    i2 = tryExtractString;
                }
            } catch (Exception unused) {
            }
        }
        arrayList.clear();
        if (i == 0) {
            UserError.Log.d(TAG, "Did not find any matches");
        } else if (i > 1) {
            UserError.Log.e(TAG, "Found too many matches: " + i);
        } else {
            handleNewValue(i2);
            return true;
        }
        return false;
    }

    int tryExtractString(String str) {
        int round;
        try {
            String filterString = filterString(str);
            if (Unitized.usingMgDl()) {
                round = Integer.parseInt(filterString);
            } else {
                if (!isValidMmol(filterString)) {
                    return -1;
                }
                double d = JoH.tolerantParseDouble(filterString, -1.0d);
                if (d == -1.0d) {
                    return -1;
                }
                round = (int) Math.round(Unitized.mgdlConvert(d));
            }
            return round;
        } catch (Exception e) {
            UserError.Log.d(TAG, "Got exception in tryExtractString: " + e);
            return -1;
        }
    }

    boolean handleNewValue(int i) {
        return handleNewValue(JoH.tsl(), i);
    }

    boolean handleNewValue(long j, int i) {
        Sensor.createDefaultIfMissing();
        String str = TAG;
        UserError.Log.d(str, "Found specific value: " + i);
        if (i >= 40 && i <= 405) {
            long currentSamplePeriod = DexCollectionType.getCurrentSamplePeriod() * 4;
            boolean z = JoH.msSince(ClassifierAction.lastReadingTimestamp) < currentSamplePeriod;
            long currentDeduplicationPeriod = (z || !isDifferentToLast(i)) ? DexCollectionType.getCurrentDeduplicationPeriod() : 10000L;
            if (!z) {
                currentSamplePeriod = currentDeduplicationPeriod;
            }
            BgReading forPreciseTimestamp = BgReading.getForPreciseTimestamp(j, currentSamplePeriod, false);
            if (forPreciseTimestamp == null) {
                if (isJammed(i)) {
                    UserError.Log.wtf(str, "Apparently value is jammed at: " + i);
                } else {
                    UserError.Log.d(str, "Inserting new value");
                    PersistentStore.setLong("UI_BASED_STORE_LAST_VALUE", i);
                    BgReading bgReadingInsertFromG5 = BgReading.bgReadingInsertFromG5(i, j);
                    if (bgReadingInsertFromG5 != null) {
                        bgReadingInsertFromG5.find_slope();
                        bgReadingInsertFromG5.noRawWillBeAvailable();
                        bgReadingInsertFromG5.injectDisplayGlucose(BestGlucose.getDisplayGlucose());
                        return true;
                    }
                }
            } else {
                UserError.Log.d(str, "Duplicate value: " + forPreciseTimestamp.timeStamp());
            }
        } else {
            UserError.Log.wtf(str, "Glucose value outside acceptable range: " + i);
        }
        return false;
    }

    static boolean isValidMmol(String str) {
        return str.matches("[0-9]+[.,][0-9]+");
    }

    private boolean isDifferentToLast(int i) {
        return PersistentStore.getLong("UI_BASED_STORE_LAST_VALUE") != ((long) i);
    }

    private boolean isJammed(int i) {
        if (PersistentStore.getLong("UI_BASED_STORE_LAST_VALUE") == i) {
            PersistentStore.incrementLong("UI_BASED_STORE_LAST_REPEAT");
        } else {
            PersistentStore.setLong("UI_BASED_STORE_LAST_REPEAT", 0L);
        }
        long j = PersistentStore.getLong("UI_BASED_STORE_LAST_REPEAT");
        UserError.Log.d(TAG, "Last repeat: " + j);
        return j > ((long) jamThreshold());
    }

    private int jamThreshold() {
        String str = this.lastPackage;
        return (str == null || !str.startsWith("com.medtronic")) ? 6 : 9;
    }

    private void getTextViews(List<TextView> list, ViewGroup viewGroup) {
        int childCount = viewGroup.getChildCount();
        for (int i = 0; i < childCount; i++) {
            View childAt = viewGroup.getChildAt(i);
            if (childAt.getVisibility() == 0) {
                if (childAt instanceof TextView) {
                    list.add((TextView) childAt);
                } else if (childAt instanceof ViewGroup) {
                    getTextViews(list, (ViewGroup) childAt);
                }
            }
        }
    }

    public static void onEnableCheckPermission(Activity activity) {
        if (DexCollectionType.getDexCollectionType() == DexCollectionType.UiBased) {
            UserError.Log.d(TAG, "Detected that we are enabled");
            switchToAndEnable(activity);
        }
    }

    public static SharedPreferences.OnSharedPreferenceChangeListener getListener(final Activity activity) {
        return new SharedPreferences.OnSharedPreferenceChangeListener() {
            @Override
            public final void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String str) {
                UiBasedCollector.lambda$getListener$0(activity, sharedPreferences, str);
            }
        };
    }

    public static void lambda$getListener$0(Activity activity, SharedPreferences sharedPreferences, String str) {
        if (str.equals("dex_collection_method")) {
            try {
                onEnableCheckPermission(activity);
            } catch (Exception unused) {
            }
        }
        if (str.equals("fetch_iob_from_companion_app")) {
            try {
                enableNotificationService(activity);
            } catch (Exception e) {
                UserError.Log.e(TAG, "Exception when enabling NotificationService: " + e);
            }
        }
    }

    public static void switchToAndEnable(Activity activity) {
        DexCollectionType.setDexCollectionType(DexCollectionType.UiBased);
        Sensor.createDefaultIfMissing();
        enableNotificationService(activity);
    }

    private static void enableNotificationService(final Activity activity) {
        if (isNotificationServiceEnabled()) {
            return;
        }
        JoH.show_ok_dialog(activity, xdrip.gs(2131756012), "Permission is needed to receive data from other applications. xDrip does not do anything beyond this scope. Please enable xDrip on the next screen", new Runnable() {
            @Override
            public final void run() {
                UiBasedCollector.lambda$enableNotificationService$1(activity);
            }
        });
    }

    public static void lambda$enableNotificationService$1(Activity activity) {
        activity.startActivity(new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS"));
    }

    private static boolean isNotificationServiceEnabled() {
        String packageName = xdrip.getAppContext().getPackageName();
        String string = Settings.Secure.getString(xdrip.getAppContext().getContentResolver(), "enabled_notification_listeners");
        if (!TextUtils.isEmpty(string)) {
            for (String str : string.split(":")) {
                ComponentName unflattenFromString = ComponentName.unflattenFromString(str);
                if (unflattenFromString != null && TextUtils.equals(packageName, unflattenFromString.getPackageName())) {
                    return true;
                }
            }
        }
        return false;
    }
}