Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 60cc9e50 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Encapsulate BatterySipper and BatteryConsumer in BatteryEntry" into sc-dev

parents 99b3468b 656c67c0
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -114,8 +114,7 @@ public class AppBatteryPreferenceController extends BasePreferenceController
            final UserManager userManager =
                    (UserManager) mContext.getSystemService(Context.USER_SERVICE);
            final BatteryEntry entry = new BatteryEntry(mContext, null, userManager, mSipper,
                    mUidBatteryConsumer);
            entry.defaultPackageName = mPackageName;
                    mUidBatteryConsumer, mPackageName);
            AdvancedPowerUsageDetail.startBatteryDetailPage(mParent.getActivity(), mParent,
                    mBatteryHelper, BatteryStats.STATS_SINCE_CHARGED, entry, mBatteryPercent);
        } else {
+12 −23
Original line number Diff line number Diff line
@@ -23,7 +23,6 @@ import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.BatteryStats;
import android.os.Bundle;
import android.os.UserHandle;
import android.text.TextUtils;
@@ -33,9 +32,7 @@ import android.view.View;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;

import com.android.internal.os.BatterySipper;
import com.android.internal.os.BatteryStatsHelper;
import com.android.internal.util.ArrayUtils;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.Utils;
@@ -109,48 +106,40 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
        helper.getStats();

        final Bundle args = new Bundle();
        final BatterySipper sipper = entry.sipper;
        final BatteryStats.Uid uid = sipper.uidObj;
        final boolean isTypeApp = sipper.drainType == BatterySipper.DrainType.APP;

        final long foregroundTimeMs = isTypeApp ? batteryUtils.getProcessTimeMs(
                BatteryUtils.StatusType.FOREGROUND, uid, which) : sipper.usageTimeMs;
        final long backgroundTimeMs = isTypeApp ? batteryUtils.getProcessTimeMs(
                BatteryUtils.StatusType.BACKGROUND, uid, which) : 0;

        if (ArrayUtils.isEmpty(sipper.mPackages)) {
        final long foregroundTimeMs = entry.getTimeInForegroundMs(batteryUtils);
        final long backgroundTimeMs = entry.getTimeInBackgroundMs(batteryUtils);
        final String packageName = entry.getDefaultPackageName();
        if (packageName == null) {
            // populate data for system app
            args.putString(EXTRA_LABEL, entry.getLabel());
            args.putInt(EXTRA_ICON_ID, entry.iconId);
            args.putString(EXTRA_PACKAGE_NAME, null);
        } else {
            // populate data for normal app
            args.putString(EXTRA_PACKAGE_NAME, entry.defaultPackageName != null
                    ? entry.defaultPackageName
                    : sipper.mPackages[0]);
            args.putString(EXTRA_PACKAGE_NAME, packageName);
        }

        args.putInt(EXTRA_UID, sipper.getUid());
        args.putInt(EXTRA_UID, entry.getUid());
        args.putLong(EXTRA_BACKGROUND_TIME, backgroundTimeMs);
        args.putLong(EXTRA_FOREGROUND_TIME, foregroundTimeMs);
        args.putString(EXTRA_POWER_USAGE_PERCENT, usagePercent);
        args.putInt(EXTRA_POWER_USAGE_AMOUNT, (int) sipper.totalPowerMah);
        args.putInt(EXTRA_POWER_USAGE_AMOUNT, (int) entry.getConsumedPower());

        new SubSettingLauncher(caller)
                .setDestination(AdvancedPowerUsageDetail.class.getName())
                .setTitleRes(R.string.battery_details_title)
                .setArguments(args)
                .setSourceMetricsCategory(fragment.getMetricsCategory())
                .setUserHandle(new UserHandle(getUserIdToLaunchAdvancePowerUsageDetail(sipper)))
                .setUserHandle(new UserHandle(getUserIdToLaunchAdvancePowerUsageDetail(entry)))
                .launch();
    }

    private static @UserIdInt
    int getUserIdToLaunchAdvancePowerUsageDetail(BatterySipper bs) {
        if (bs.drainType == BatterySipper.DrainType.USER) {
    private static @UserIdInt int getUserIdToLaunchAdvancePowerUsageDetail(
            BatteryEntry batteryEntry) {
        if (batteryEntry.isUserEntry()) {
            return ActivityManager.getCurrentUser();
        }
        return UserHandle.getUserId(bs.getUid());
        return UserHandle.getUserId(batteryEntry.getUid());
    }

    public static void startBatteryDetailPage(Activity caller,
+5 −4
Original line number Diff line number Diff line
@@ -85,15 +85,16 @@ public class BatteryAppListPreferenceController extends AbstractPreferenceContro
            switch (msg.what) {
                case BatteryEntry.MSG_UPDATE_NAME_ICON:
                    BatteryEntry entry = (BatteryEntry) msg.obj;
                    int uid = entry.getUid();
                    PowerGaugePreference pgp =
                            (PowerGaugePreference) mAppListGroup.findPreference(
                                    Integer.toString(entry.sipper.uidObj.getUid()));
                                    Integer.toString(uid));
                    if (pgp != null) {
                        final int userId = UserHandle.getUserId(entry.sipper.getUid());
                        final int userId = UserHandle.getUserId(uid);
                        final UserHandle userHandle = new UserHandle(userId);
                        pgp.setIcon(mUserManager.getBadgedIconForUser(entry.getIcon(), userHandle));
                        pgp.setTitle(entry.name);
                        if (entry.sipper.drainType == DrainType.APP) {
                        if (entry.isAppEntry()) {
                            pgp.setContentDescription(entry.name);
                        }
                    }
@@ -208,7 +209,7 @@ public class BatteryAppListPreferenceController extends AbstractPreferenceContro
                }
                final UserHandle userHandle = new UserHandle(UserHandle.getUserId(sipper.getUid()));
                final BatteryEntry entry = new BatteryEntry(mActivity, mHandler, mUserManager,
                        sipper, null);
                        sipper, null, null);
                final Drawable badgedIcon = mUserManager.getBadgedIconForUser(entry.getIcon(),
                        userHandle);
                final CharSequence contentDescription = mUserManager.getBadgedLabelForUser(
+140 −39
Original line number Diff line number Diff line
@@ -25,15 +25,19 @@ import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.UserInfo;
import android.graphics.drawable.Drawable;
import android.os.BatteryConsumer;
import android.os.BatteryStats;
import android.os.Handler;
import android.os.Process;
import android.os.RemoteException;
import android.os.UidBatteryConsumer;
import android.os.UserBatteryConsumer;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.Log;

import com.android.internal.os.BatterySipper;
import com.android.internal.util.ArrayUtils;
import com.android.settings.R;
import com.android.settingslib.Utils;

@@ -122,13 +126,13 @@ public class BatteryEntry {
    }

    public final Context context;
    public final BatterySipper sipper;
    public final UidBatteryConsumer uidBatteryConsumer;
    private final BatterySipper mSipper;
    private final BatteryConsumer mBatteryConsumer;

    public String name;
    public Drawable icon;
    public int iconId; // For passing to the detail screen.
    public String defaultPackageName;
    private String mDefaultPackageName;

    static class UidToDetail {
        String name;
@@ -137,37 +141,38 @@ public class BatteryEntry {
    }

    public BatteryEntry(Context context, Handler handler, UserManager um, BatterySipper sipper,
            UidBatteryConsumer uidBatteryConsumer) {
            BatteryConsumer batteryConsumer, String packageName) {
        sHandler = handler;
        this.context = context;
        this.sipper = sipper;
        this.uidBatteryConsumer = uidBatteryConsumer;
        this.mSipper = sipper;
        this.mBatteryConsumer = batteryConsumer;
        this.mDefaultPackageName = packageName;

        // This condition is met when BatteryEntry is initialized from BatteryUsageStats.
        // Once the conversion from BatteryStatsHelper is completed, the condition will
        // always be true and can be removed.
        if (uidBatteryConsumer != null) {
            PackageManager pm = context.getPackageManager();
        if (batteryConsumer instanceof UidBatteryConsumer) {
            UidBatteryConsumer uidBatteryConsumer = (UidBatteryConsumer) batteryConsumer;
            int uid = uidBatteryConsumer.getUid();
            PackageManager pm = context.getPackageManager();
            if (mDefaultPackageName == null) {
                String[] packages = pm.getPackagesForUid(uid);
                // Apps should only have one package
            if (packages == null || packages.length != 1) {
                name = uidBatteryConsumer.getPackageWithHighestDrain();
                if (packages != null && packages.length == 1) {
                    mDefaultPackageName = packages[0];
                } else {
                defaultPackageName = packages[0];
                    mDefaultPackageName = uidBatteryConsumer.getPackageWithHighestDrain();
                }
            }
            if (mDefaultPackageName != null) {
                try {
                    ApplicationInfo appInfo =
                            pm.getApplicationInfo(defaultPackageName, 0 /* no flags */);
                            pm.getApplicationInfo(mDefaultPackageName, 0 /* no flags */);
                    name = pm.getApplicationLabel(appInfo).toString();
                } catch (NameNotFoundException e) {
                    Log.d(TAG, "PackageManager failed to retrieve ApplicationInfo for: "
                            + defaultPackageName);
                    name = defaultPackageName;
                            + mDefaultPackageName);
                    name = mDefaultPackageName;
                }
            }
            if ((name == null || iconId == 0) && uid != 0) {
            getQuickNameIconForUid(uid);
            }
            return;
        }

@@ -207,15 +212,15 @@ public class BatteryEntry {
                if (sipper.mPackages == null || sipper.mPackages.length != 1) {
                    name = sipper.packageWithHighestDrain;
                } else {
                    defaultPackageName = pm.getPackagesForUid(sipper.uidObj.getUid())[0];
                    mDefaultPackageName = pm.getPackagesForUid(sipper.uidObj.getUid())[0];
                    try {
                        ApplicationInfo appInfo =
                            pm.getApplicationInfo(defaultPackageName, 0 /* no flags */);
                                pm.getApplicationInfo(mDefaultPackageName, 0 /* no flags */);
                        name = pm.getApplicationLabel(appInfo).toString();
                    } catch (NameNotFoundException e) {
                        Log.d(TAG, "PackageManager failed to retrieve ApplicationInfo for: "
                            + defaultPackageName);
                        name = defaultPackageName;
                                + mDefaultPackageName);
                        name = mDefaultPackageName;
                    }
                }
                break;
@@ -250,8 +255,8 @@ public class BatteryEntry {
        if (iconId > 0) {
            icon = context.getDrawable(iconId);
        }
        if ((name == null || iconId == 0) && this.sipper.uidObj != null) {
            getQuickNameIconForUid(this.sipper.uidObj.getUid());
        if ((name == null || iconId == 0) && sipper.uidObj != null) {
            getQuickNameIconForUid(sipper.uidObj.getUid());
        }
    }

@@ -277,7 +282,7 @@ public class BatteryEntry {
        final String uidString = Integer.toString(uid);
        if (sUidCache.containsKey(uidString)) {
            UidToDetail utd = sUidCache.get(uidString);
            defaultPackageName = utd.packageName;
            mDefaultPackageName = utd.packageName;
            name = utd.name;
            icon = utd.icon;
            return;
@@ -308,17 +313,17 @@ public class BatteryEntry {
     */
    public void loadNameAndIcon() {
        // Bail out if the current sipper is not an App sipper.
        if (sipper.uidObj == null) {
        if (mSipper.uidObj == null) {
            return;
        }

        PackageManager pm = context.getPackageManager();
        final int uid = sipper.uidObj.getUid();
        if (sipper.mPackages == null) {
            sipper.mPackages = pm.getPackagesForUid(uid);
        final int uid = mSipper.uidObj.getUid();
        if (mSipper.mPackages == null) {
            mSipper.mPackages = pm.getPackagesForUid(uid);
        }

        final String[] packages = extractPackagesFromSipper(sipper);
        final String[] packages = extractPackagesFromSipper(mSipper);
        if (packages != null) {
            String[] packageLabels = new String[packages.length];
            System.arraycopy(packages, 0, packageLabels, 0, packages.length);
@@ -340,7 +345,7 @@ public class BatteryEntry {
                        packageLabels[i] = label.toString();
                    }
                    if (ai.icon != 0) {
                        defaultPackageName = packages[i];
                        mDefaultPackageName = packages[i];
                        icon = ai.loadIcon(pm);
                        break;
                    }
@@ -368,7 +373,7 @@ public class BatteryEntry {
                            if (nm != null) {
                                name = nm.toString();
                                if (pi.applicationInfo.icon != 0) {
                                    defaultPackageName = pkgName;
                                    mDefaultPackageName = pkgName;
                                    icon = pi.applicationInfo.loadIcon(pm);
                                }
                                break;
@@ -394,17 +399,113 @@ public class BatteryEntry {
        UidToDetail utd = new UidToDetail();
        utd.name = name;
        utd.icon = icon;
        utd.packageName = defaultPackageName;
        utd.packageName = mDefaultPackageName;
        sUidCache.put(uidString, utd);
        if (sHandler != null) {
            sHandler.sendMessage(sHandler.obtainMessage(MSG_UPDATE_NAME_ICON, this));
        }
    }

    String[] extractPackagesFromSipper(BatterySipper sipper) {
    static String[] extractPackagesFromSipper(BatterySipper sipper) {
        // Only use system package if uid is system uid, so it could find a consistent name and icon
        return sipper.getUid() == Process.SYSTEM_UID
                ? new String[]{PACKAGE_SYSTEM}
                : sipper.mPackages;
    }

    /**
     * Returns true if this entry describes an app (UID)
     */
    public boolean isAppEntry() {
        if (mBatteryConsumer instanceof UidBatteryConsumer) {
            return true;
        } else {
            return mSipper.drainType == BatterySipper.DrainType.APP;
        }
    }

    /**
     * Returns true if this entry describes a User.
     */
    public boolean isUserEntry() {
        if (mBatteryConsumer instanceof UserBatteryConsumer) {
            return true;
        } else {
            return mSipper.drainType == BatterySipper.DrainType.USER;
        }
    }

    /**
     * Returns the package name that should be used to represent the UID described
     * by this entry.
     */
    public String getDefaultPackageName() {
        if (mDefaultPackageName != null) {
            return mDefaultPackageName;
        }
        if (ArrayUtils.isEmpty(mSipper.mPackages)) {
            return null;
        } else {
            return mSipper.mPackages[0];
        }
    }

    /**
     * Returns the UID of the app described by this entry.
     */
    public int getUid() {
        if (mBatteryConsumer instanceof UidBatteryConsumer) {
            return ((UidBatteryConsumer) mBatteryConsumer).getUid();
        } else if (mBatteryConsumer != null) {
            return Process.INVALID_UID;
        } else {
            return mSipper.getUid();
        }
    }

    /**
     * Returns foreground foreground time (in milliseconds) that is attributed to this entry.
     */
    public long getTimeInForegroundMs(BatteryUtils batteryUtils) {
        if (mBatteryConsumer instanceof UidBatteryConsumer) {
            return ((UidBatteryConsumer) mBatteryConsumer).getTimeInStateMs(
                    UidBatteryConsumer.STATE_FOREGROUND);
        } else if (mBatteryConsumer != null) {
            return mBatteryConsumer.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_USAGE);
        } else if (mSipper.drainType == BatterySipper.DrainType.APP) {
            return batteryUtils.getProcessTimeMs(
                    BatteryUtils.StatusType.FOREGROUND, mSipper.uidObj,
                    BatteryStats.STATS_SINCE_CHARGED);
        } else {
            return mSipper.usageTimeMs;
        }
    }

    /**
     * Returns background activity time (in milliseconds) that is attributed to this entry.
     */
    public long getTimeInBackgroundMs(BatteryUtils batteryUtils) {
        if (mBatteryConsumer instanceof UidBatteryConsumer) {
            return ((UidBatteryConsumer) mBatteryConsumer).getTimeInStateMs(
                    UidBatteryConsumer.STATE_BACKGROUND);
        } else if (mBatteryConsumer != null) {
            return 0;
        } else  if (mSipper.drainType == BatterySipper.DrainType.APP) {
            return batteryUtils.getProcessTimeMs(
                    BatteryUtils.StatusType.BACKGROUND, mSipper.uidObj,
                    BatteryStats.STATS_SINCE_CHARGED);
        } else {
            return 0;
        }
    }

    /**
     * Returns total amount of power (in milli-amp-hours) that is attributed to this entry.
     */
    public double getConsumedPower() {
        if (mBatteryConsumer != null) {
            return mBatteryConsumer.getConsumedPower();
        }
        return (int) mSipper.totalPowerMah;
    }
}
+14 −52
Original line number Diff line number Diff line
@@ -47,7 +47,6 @@ import androidx.loader.app.LoaderManager;
import androidx.preference.Preference;
import androidx.recyclerview.widget.RecyclerView;

import com.android.internal.os.BatterySipper;
import com.android.internal.os.BatteryStatsHelper;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
@@ -114,12 +113,8 @@ public class AdvancedPowerUsageDetailTest {
    @Mock
    private BatteryEntry mBatteryEntry;
    @Mock
    private BatterySipper mBatterySipper;
    @Mock
    private BatteryStatsHelper mBatteryStatsHelper;
    @Mock
    private BatteryStats.Uid mUid;
    @Mock
    private PackageManager mPackageManager;
    @Mock
    private AppOpsManager mAppOpsManager;
@@ -140,6 +135,7 @@ public class AdvancedPowerUsageDetailTest {
        MockitoAnnotations.initMocks(this);

        mContext = spy(RuntimeEnvironment.application);
        when(mContext.getPackageName()).thenReturn("foo");
        FakeFeatureFactory.setupForTest();

        mFragment = spy(new AdvancedPowerUsageDetail());
@@ -168,19 +164,13 @@ public class AdvancedPowerUsageDetailTest {
        doReturn(mEntityHeaderController).when(mEntityHeaderController)
                .setSummary(nullable(String.class));

        doReturn(UID).when(mBatterySipper).getUid();
        when(mBatteryEntry.getUid()).thenReturn(UID);
        when(mBatteryEntry.getLabel()).thenReturn(APP_LABEL);
        doReturn(BACKGROUND_TIME_US).when(mUid).getProcessStateTime(
                eq(BatteryStats.Uid.PROCESS_STATE_BACKGROUND), anyLong(), anyInt());
        doReturn(PROCSTATE_TOP_TIME_US).when(mUid).getProcessStateTime(
                eq(BatteryStats.Uid.PROCESS_STATE_TOP), anyLong(), anyInt());
        doReturn(mForegroundActivityTimer).when(mUid).getForegroundActivityTimer();
        doReturn(FOREGROUND_ACTIVITY_TIME_US).when(mForegroundActivityTimer)
                .getTotalTimeLocked(anyLong(), anyInt());
        ReflectionHelpers.setField(mBatteryEntry, "sipper", mBatterySipper);
        when(mBatteryEntry.getTimeInBackgroundMs(any(BatteryUtils.class)))
                .thenReturn(BACKGROUND_TIME_MS);
        when(mBatteryEntry.getTimeInForegroundMs(any(BatteryUtils.class)))
                .thenReturn(FOREGROUND_TIME_MS);
        mBatteryEntry.iconId = ICON_ID;
        mBatterySipper.uidObj = mUid;
        mBatterySipper.drainType = BatterySipper.DrainType.APP;

        mFragment.mHeaderPreference = mHeaderPreference;
        mFragment.mState = mState;
@@ -200,6 +190,7 @@ public class AdvancedPowerUsageDetailTest {

        Answer<Void> callable = invocation -> {
            mBundle = captor.getValue().getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS);
            System.out.println("mBundle = " + mBundle);
            return null;
        };
        doAnswer(callable).when(mActivity).startActivityAsUser(captor.capture(),
@@ -274,27 +265,10 @@ public class AdvancedPowerUsageDetailTest {
            .isEqualTo(USAGE_PERCENT);
    }

    @Test
    public void testStartBatteryDetailPage_typeNotApp_hasBasicData() {
        mBatterySipper.drainType = BatterySipper.DrainType.PHONE;
        mBatterySipper.usageTimeMs = PHONE_FOREGROUND_TIME_MS;

        AdvancedPowerUsageDetail.startBatteryDetailPage(mActivity, mBatteryUtils, mFragment,
                mBatteryStatsHelper, 0, mBatteryEntry, USAGE_PERCENT);

        assertThat(mBundle.getInt(AdvancedPowerUsageDetail.EXTRA_UID)).isEqualTo(UID);
        assertThat(mBundle.getLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME))
            .isEqualTo(PHONE_FOREGROUND_TIME_MS);
        assertThat(mBundle.getLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME))
            .isEqualTo(PHONE_BACKGROUND_TIME_MS);
        assertThat(mBundle.getString(AdvancedPowerUsageDetail.EXTRA_POWER_USAGE_PERCENT))
            .isEqualTo(USAGE_PERCENT);
    }

    @Test
    public void testStartBatteryDetailPage_NormalApp() {
        mBatterySipper.mPackages = PACKAGE_NAME;
        mBatteryEntry.defaultPackageName = PACKAGE_NAME[0];
        when(mBatteryEntry.getDefaultPackageName()).thenReturn(PACKAGE_NAME[0]);

        AdvancedPowerUsageDetail.startBatteryDetailPage(mActivity, mBatteryUtils, mFragment,
                mBatteryStatsHelper, 0, mBatteryEntry, USAGE_PERCENT);

@@ -304,7 +278,8 @@ public class AdvancedPowerUsageDetailTest {

    @Test
    public void testStartBatteryDetailPage_SystemApp() {
        mBatterySipper.mPackages = null;
        when(mBatteryEntry.getDefaultPackageName()).thenReturn(null);

        AdvancedPowerUsageDetail.startBatteryDetailPage(mActivity, mBatteryUtils, mFragment,
                mBatteryStatsHelper, 0, mBatteryEntry, USAGE_PERCENT);

@@ -316,8 +291,8 @@ public class AdvancedPowerUsageDetailTest {
    @Test
    public void testStartBatteryDetailPage_WorkApp() {
        final int appUid = 1010019;
        mBatterySipper.mPackages = PACKAGE_NAME;
        doReturn(appUid).when(mBatterySipper).getUid();
        doReturn(appUid).when(mBatteryEntry).getUid();

        AdvancedPowerUsageDetail.startBatteryDetailPage(mActivity, mBatteryUtils, mFragment,
                mBatteryStatsHelper, 0, mBatteryEntry, USAGE_PERCENT);

@@ -326,8 +301,7 @@ public class AdvancedPowerUsageDetailTest {

    @Test
    public void testStartBatteryDetailPage_typeUser_startByCurrentUser() {
        mBatterySipper.drainType = BatterySipper.DrainType.USER;
        mBatterySipper.userId = 10;
        when(mBatteryEntry.isUserEntry()).thenReturn(true);

        final int currentUser = 20;
        ShadowActivityManager.setCurrentUser(currentUser);
@@ -364,18 +338,6 @@ public class AdvancedPowerUsageDetailTest {
        assertThat(mBundle.getInt(AdvancedPowerUsageDetail.EXTRA_UID)).isEqualTo(UID);
    }

    @Test
    public void testStartBatteryDetailPage_defaultPackageNull_chooseFromBatterySipper() {
        mBatteryEntry.defaultPackageName = null;
        mBatteryEntry.sipper.mPackages = PACKAGE_NAME;

        AdvancedPowerUsageDetail.startBatteryDetailPage(mActivity, mBatteryUtils, mFragment,
                mBatteryStatsHelper, 0, mBatteryEntry, USAGE_PERCENT);

        assertThat(mBundle.getString(AdvancedPowerUsageDetail.EXTRA_PACKAGE_NAME))
            .isEqualTo(PACKAGE_NAME[0]);
    }

    @Test
    public void testInitPreference_hasCorrectSummary() {
        Bundle bundle = new Bundle(4);
Loading