Merge "Developer setting to enable notification channel warnings" into oc-dev
diff --git a/src/com/android/settings/applications/InstalledAppDetails.java b/src/com/android/settings/applications/InstalledAppDetails.java
index e9b7481..ab9f358 100755
--- a/src/com/android/settings/applications/InstalledAppDetails.java
+++ b/src/com/android/settings/applications/InstalledAppDetails.java
@@ -93,6 +93,7 @@
 import com.android.settings.datausage.DataUsageSummary;
 import com.android.settings.fuelgauge.AdvancedPowerUsageDetail;
 import com.android.settings.fuelgauge.BatteryEntry;
+import com.android.settings.fuelgauge.BatteryStatsHelperLoader;
 import com.android.settings.fuelgauge.BatteryUtils;
 import com.android.settings.notification.AppNotificationSettings;
 import com.android.settings.notification.NotificationBackend;
@@ -143,6 +144,7 @@
 
     private static final int LOADER_CHART_DATA = 2;
     private static final int LOADER_STORAGE = 3;
+    private static final int LOADER_BATTERY = 4;
 
     private static final int DLG_FORCE_STOP = DLG_BASE + 1;
     private static final int DLG_DISABLE = DLG_BASE + 2;
@@ -204,6 +206,31 @@
     private String mBatteryPercent;
     private BatteryUtils mBatteryUtils;
 
+    private final LoaderCallbacks<BatteryStatsHelper> mBatteryCallbacks =
+            new LoaderCallbacks<BatteryStatsHelper>() {
+
+                @Override
+                public Loader<BatteryStatsHelper> onCreateLoader(int id, Bundle args) {
+                    return new BatteryStatsHelperLoader(getContext(), args);
+                }
+
+                @Override
+                public void onLoadFinished(Loader<BatteryStatsHelper> loader,
+                        BatteryStatsHelper batteryHelper) {
+                    mBatteryHelper = batteryHelper;
+                    if (mPackageInfo != null) {
+                        mSipper = findTargetSipper(batteryHelper, mPackageInfo.applicationInfo.uid);
+                        if (getActivity() != null) {
+                            updateBattery();
+                        }
+                    }
+                }
+
+                @Override
+                public void onLoaderReset(Loader<BatteryStatsHelper> loader) {
+                }
+            };
+
     private boolean handleDisableable(Button button) {
         boolean disableable = false;
         // Try to prevent the user from bricking their phone
@@ -362,7 +389,6 @@
         } else {
             removePreference(KEY_DATA);
         }
-        mBatteryHelper = new BatteryStatsHelper(getActivity(), true);
         mBatteryUtils = BatteryUtils.getInstance(getContext());
     }
 
@@ -386,7 +412,7 @@
                     mDataCallbacks);
             loaderManager.restartLoader(LOADER_STORAGE, Bundle.EMPTY, this);
         }
-        new BatteryUpdater().execute();
+        getLoaderManager().initLoader(LOADER_BATTERY, Bundle.EMPTY, mBatteryCallbacks);
         new MemoryUpdater().execute();
         updateDynamicPrefs();
     }
@@ -625,6 +651,19 @@
         return showIt;
     }
 
+    @VisibleForTesting
+    BatterySipper findTargetSipper(BatteryStatsHelper batteryHelper, int uid) {
+        List<BatterySipper> usageList = batteryHelper.getUsageList();
+        for (int i = 0, size = usageList.size(); i < size; i++) {
+            BatterySipper sipper = usageList.get(i);
+            if (sipper.getUid() == uid) {
+                return sipper;
+            }
+        }
+
+        return null;
+    }
+
     private boolean signaturesMatch(String pkg1, String pkg2) {
         if (pkg1 != null && pkg2 != null) {
             try {
@@ -719,7 +758,7 @@
     }
 
     private void updateBattery() {
-        if (mSipper != null) {
+        if (mSipper != null && mBatteryHelper != null) {
             mBatteryPreference.setEnabled(true);
             final int dischargeAmount = mBatteryHelper.getStats().getDischargeAmount(
                     BatteryStats.STATS_SINCE_CHARGED);
@@ -1343,33 +1382,6 @@
 
     }
 
-    private class BatteryUpdater extends AsyncTask<Void, Void, Void> {
-        @Override
-        protected Void doInBackground(Void... params) {
-            mBatteryHelper.create((Bundle) null);
-            mBatteryHelper.refreshStats(BatteryStats.STATS_SINCE_CHARGED,
-                    mUserManager.getUserProfiles());
-            List<BatterySipper> usageList = mBatteryHelper.getUsageList();
-            final int N = usageList.size();
-            for (int i = 0; i < N; i++) {
-                BatterySipper sipper = usageList.get(i);
-                if (sipper.getUid() == mPackageInfo.applicationInfo.uid) {
-                    mSipper = sipper;
-                    break;
-                }
-            }
-            return null;
-        }
-
-        @Override
-        protected void onPostExecute(Void result) {
-            if (getActivity() == null) {
-                return;
-            }
-            refreshUi();
-        }
-    }
-
     /**
      * Elicit this class for testing. Test cannot be done in robolectric because it
      * invokes the new API.
diff --git a/src/com/android/settings/fingerprint/FingerprintEnrollEnrolling.java b/src/com/android/settings/fingerprint/FingerprintEnrollEnrolling.java
index e6e6bcd..8078ad6 100644
--- a/src/com/android/settings/fingerprint/FingerprintEnrollEnrolling.java
+++ b/src/com/android/settings/fingerprint/FingerprintEnrollEnrolling.java
@@ -159,6 +159,14 @@
         startIconAnimation();
     }
 
+    @Override
+    protected void onPause() {
+        super.onPause();
+        if (mSidecar != null) {
+            mSidecar.setListener(null);
+        }
+    }
+
     private void startIconAnimation() {
         mIconAnimationDrawable.start();
     }
diff --git a/src/com/android/settings/fingerprint/FingerprintEnrollSidecar.java b/src/com/android/settings/fingerprint/FingerprintEnrollSidecar.java
index 7fc7a04..cbfec0c 100644
--- a/src/com/android/settings/fingerprint/FingerprintEnrollSidecar.java
+++ b/src/com/android/settings/fingerprint/FingerprintEnrollSidecar.java
@@ -31,6 +31,8 @@
 import com.android.settings.core.InstrumentedFragment;
 import com.android.settings.password.IFingerprintManager;
 
+import java.util.ArrayList;
+
 /**
  * Sidecar fragment to handle the state around fingerprint enrollment.
  */
@@ -46,6 +48,57 @@
     private boolean mDone;
     private int mUserId;
     private IFingerprintManager mFingerprintManager;
+    private ArrayList<QueuedEvent> mQueuedEvents;
+
+    private abstract class QueuedEvent {
+        public abstract void send(Listener listener);
+    }
+
+    private class QueuedEnrollmentProgress extends QueuedEvent {
+        int enrollmentSteps;
+        int remaining;
+        public QueuedEnrollmentProgress(int enrollmentSteps, int remaining) {
+            this.enrollmentSteps = enrollmentSteps;
+            this.remaining = remaining;
+        }
+
+        @Override
+        public void send(Listener listener) {
+            listener.onEnrollmentProgressChange(enrollmentSteps, remaining);
+        }
+    }
+
+    private class QueuedEnrollmentHelp extends QueuedEvent {
+        int helpMsgId;
+        CharSequence helpString;
+        public QueuedEnrollmentHelp(int helpMsgId, CharSequence helpString) {
+            this.helpMsgId = helpMsgId;
+            this.helpString = helpString;
+        }
+
+        @Override
+        public void send(Listener listener) {
+            listener.onEnrollmentHelp(helpString);
+        }
+    }
+
+    private class QueuedEnrollmentError extends QueuedEvent {
+        int errMsgId;
+        CharSequence errString;
+        public QueuedEnrollmentError(int errMsgId, CharSequence errString) {
+            this.errMsgId = errMsgId;
+            this.errString = errString;
+        }
+
+        @Override
+        public void send(Listener listener) {
+            listener.onEnrollmentError(errMsgId, errString);
+        }
+    }
+
+    public FingerprintEnrollSidecar() {
+        mQueuedEvents = new ArrayList<>();
+    }
 
     @Override
     public void onCreate(@Nullable Bundle savedInstanceState) {
@@ -103,6 +156,13 @@
 
     public void setListener(Listener listener) {
         mListener = listener;
+        if (mListener != null) {
+            for (int i=0; i<mQueuedEvents.size(); i++) {
+                QueuedEvent event = mQueuedEvents.get(i);
+                event.send(mListener);
+            }
+            mQueuedEvents.clear();
+        }
     }
 
     public int getEnrollmentSteps() {
@@ -129,6 +189,8 @@
             mDone = remaining == 0;
             if (mListener != null) {
                 mListener.onEnrollmentProgressChange(mEnrollmentSteps, remaining);
+            } else {
+                mQueuedEvents.add(new QueuedEnrollmentProgress(mEnrollmentSteps, remaining));
             }
         }
 
@@ -136,6 +198,8 @@
         public void onEnrollmentHelp(int helpMsgId, CharSequence helpString) {
             if (mListener != null) {
                 mListener.onEnrollmentHelp(helpString);
+            } else {
+                mQueuedEvents.add(new QueuedEnrollmentHelp(helpMsgId, helpString));
             }
         }
 
@@ -143,6 +207,8 @@
         public void onEnrollmentError(int errMsgId, CharSequence errString) {
             if (mListener != null) {
                 mListener.onEnrollmentError(errMsgId, errString);
+            } else {
+                mQueuedEvents.add(new QueuedEnrollmentError(errMsgId, errString));
             }
             mEnrolling = false;
         }
diff --git a/src/com/android/settings/fuelgauge/BatteryMeterView.java b/src/com/android/settings/fuelgauge/BatteryMeterView.java
index 969f886..c450b90 100644
--- a/src/com/android/settings/fuelgauge/BatteryMeterView.java
+++ b/src/com/android/settings/fuelgauge/BatteryMeterView.java
@@ -38,8 +38,6 @@
     @VisibleForTesting
     ColorFilter mAccentColorFilter;
 
-    private int mLevel;
-
     public BatteryMeterView(Context context) {
         this(context, null, 0);
     }
@@ -66,7 +64,6 @@
     }
 
     public void setBatteryLevel(int level) {
-        mLevel = level;
         mDrawable.setBatteryLevel(level);
         if (level < mDrawable.getCriticalLevel()) {
             mDrawable.setBatteryColorFilter(mErrorColorFilter);
@@ -75,10 +72,6 @@
         }
     }
 
-    public int getBatteryLevel() {
-        return mLevel;
-    }
-
     public void setCharging(boolean charging) {
         mDrawable.setCharging(charging);
     }
diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
index 9ee71dd..b3d07b8 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
@@ -16,8 +16,6 @@
 
 package com.android.settings.fuelgauge;
 
-import android.animation.Animator;
-import android.animation.ValueAnimator;
 import android.app.Activity;
 import android.content.Context;
 import android.content.Intent;
@@ -43,7 +41,6 @@
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
-import android.view.animation.AnimationUtils;
 import android.widget.TextView;
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -87,10 +84,6 @@
     private static final String KEY_BATTERY_HEADER = "battery_header";
     private static final int MAX_ITEMS_TO_LIST = USE_FAKE_DATA ? 30 : 10;
     private static final int MIN_AVERAGE_POWER_THRESHOLD_MILLI_AMP = 10;
-    private static final int BATTERY_ANIMATION_DURATION_MS_PER_LEVEL = 30;
-
-    @VisibleForTesting
-    static final String ARG_BATTERY_LEVEL = "key_battery_level";
 
     private static final String KEY_SCREEN_USAGE = "screen_usage";
     private static final String KEY_TIME_SINCE_LAST_FULL_CHARGE = "last_full_charge";
@@ -112,8 +105,6 @@
             new FooterPreferenceMixin(this, getLifecycle());
 
     @VisibleForTesting
-    int mBatteryLevel;
-    @VisibleForTesting
     boolean mShowAllApps = false;
     @VisibleForTesting
     PowerGaugePreference mScreenUsagePref;
@@ -133,8 +124,6 @@
         super.onCreate(icicle);
         setAnimationAllowed(true);
 
-        mBatteryLevel = getContext().getResources().getInteger(
-                com.android.internal.R.integer.config_criticalBatteryWarningLevel) + 1;
         mBatteryLayoutPref = (LayoutPreference) findPreference(KEY_BATTERY_HEADER);
         mAppListGroup = (PreferenceGroup) findPreference(KEY_APP_LIST);
         mScreenUsagePref = (PowerGaugePreference) findPreference(KEY_SCREEN_USAGE);
@@ -148,14 +137,6 @@
     }
 
     @Override
-    public void onActivityCreated(Bundle savedInstanceState) {
-        super.onActivityCreated(savedInstanceState);
-        if (savedInstanceState != null) {
-            mBatteryLevel = savedInstanceState.getInt(ARG_BATTERY_LEVEL);
-        }
-    }
-
-    @Override
     public int getMetricsCategory() {
         return MetricsEvent.FUELGAUGE_POWER_USAGE_SUMMARY;
     }
@@ -163,8 +144,6 @@
     @Override
     public void onResume() {
         super.onResume();
-
-        initHeaderPreference();
     }
 
     @Override
@@ -183,12 +162,6 @@
     }
 
     @Override
-    public void onSaveInstanceState(Bundle outState) {
-        super.onSaveInstanceState(outState);
-        outState.putInt(ARG_BATTERY_LEVEL, mBatteryLevel);
-    }
-
-    @Override
     public boolean onPreferenceTreeClick(Preference preference) {
         if (KEY_BATTERY_HEADER.equals(preference.getKey())) {
             performBatteryHeaderClick();
@@ -596,46 +569,15 @@
                 .findViewById(R.id.battery_header_icon);
         final TextView timeText = (TextView) mBatteryLayoutPref.findViewById(R.id.battery_percent);
         final TextView summary1 = (TextView) mBatteryLayoutPref.findViewById(R.id.summary1);
+        timeText.setText(Utils.formatPercentage(info.batteryLevel));
         if (info.remainingLabel == null ) {
             summary1.setText(info.statusLabel);
         } else {
             summary1.setText(info.remainingLabel);
         }
+
+        batteryView.setBatteryLevel(info.batteryLevel);
         batteryView.setCharging(!info.discharging);
-        startBatteryHeaderAnimationIfNecessary(batteryView, timeText, mBatteryLevel,
-                info.batteryLevel);
-    }
-
-    @VisibleForTesting
-    void initHeaderPreference() {
-        final BatteryMeterView batteryView = (BatteryMeterView) mBatteryLayoutPref
-                .findViewById(R.id.battery_header_icon);
-        final TextView timeText = (TextView) mBatteryLayoutPref.findViewById(R.id.battery_percent);
-
-        batteryView.setBatteryLevel(mBatteryLevel);
-        timeText.setText(Utils.formatPercentage(mBatteryLevel));
-    }
-
-    @VisibleForTesting
-    void startBatteryHeaderAnimationIfNecessary(BatteryMeterView batteryView, TextView timeTextView,
-            int prevLevel, int currentLevel) {
-        mBatteryLevel = currentLevel;
-        final int diff = Math.abs(prevLevel - currentLevel);
-        if (diff != 0) {
-            final ValueAnimator animator = ValueAnimator.ofInt(prevLevel, currentLevel);
-            animator.setDuration(BATTERY_ANIMATION_DURATION_MS_PER_LEVEL * diff);
-            animator.setInterpolator(AnimationUtils.loadInterpolator(getContext(),
-                    android.R.interpolator.fast_out_slow_in));
-            animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
-                @Override
-                public void onAnimationUpdate(ValueAnimator animation) {
-                    final Integer level = (Integer) animation.getAnimatedValue();
-                    batteryView.setBatteryLevel(level);
-                    timeTextView.setText(Utils.formatPercentage(level));
-                }
-            });
-            animator.start();
-        }
     }
 
     @VisibleForTesting
diff --git a/tests/robotests/src/com/android/settings/applications/InstalledAppDetailsTest.java b/tests/robotests/src/com/android/settings/applications/InstalledAppDetailsTest.java
index 17910bf..a09aeec 100644
--- a/tests/robotests/src/com/android/settings/applications/InstalledAppDetailsTest.java
+++ b/tests/robotests/src/com/android/settings/applications/InstalledAppDetailsTest.java
@@ -18,6 +18,7 @@
 
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Mockito.doReturn;
@@ -65,12 +66,17 @@
 import org.robolectric.annotation.Config;
 import org.robolectric.util.ReflectionHelpers;
 
+import java.util.ArrayList;
+import java.util.List;
+
 
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public final class InstalledAppDetailsTest {
 
     private static final String PACKAGE_NAME = "test_package_name";
+    private static final int TARGET_UID = 111;
+    private static final int OTHER_UID = 222;
 
     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     private Context mContext;
@@ -87,6 +93,8 @@
     @Mock
     private BatterySipper mBatterySipper;
     @Mock
+    private BatterySipper mOtherBatterySipper;
+    @Mock
     private BatteryStatsHelper mBatteryStatsHelper;
     @Mock
     private BatteryStats.Uid mUid;
@@ -105,6 +113,8 @@
 
         mBatterySipper.drainType = BatterySipper.DrainType.IDLE;
         mBatterySipper.uidObj = mUid;
+        doReturn(TARGET_UID).when(mBatterySipper).getUid();
+        doReturn(OTHER_UID).when(mOtherBatterySipper).getUid();
         doReturn(mActivity).when(mAppDetail).getActivity();
         doReturn(mShadowContext).when(mAppDetail).getContext();
         doReturn(mPackageManager).when(mActivity).getPackageManager();
@@ -388,4 +398,15 @@
 
         verify(mActivity).invalidateOptionsMenu();
     }
+
+    @Test
+    public void findTargetSipper_findCorrectSipper() {
+        List<BatterySipper> usageList = new ArrayList<>();
+        usageList.add(mBatterySipper);
+        usageList.add(mOtherBatterySipper);
+        doReturn(usageList).when(mBatteryStatsHelper).getUsageList();
+
+        assertThat(mAppDetail.findTargetSipper(mBatteryStatsHelper, TARGET_UID)).isEqualTo(
+                mBatterySipper);
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
index ed78783..615424c 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
@@ -17,7 +17,6 @@
 
 import android.content.Context;
 import android.content.Intent;
-import android.os.Bundle;
 import android.os.PowerManager;
 import android.os.Process;
 import android.text.TextUtils;
@@ -130,6 +129,8 @@
     @Mock
     private LayoutPreference mBatteryLayoutPref;
     @Mock
+    private TextView mBatteryPercentText;
+    @Mock
     private TextView mSummary1;
     @Mock
     private BatteryInfo mBatteryInfo;
@@ -140,7 +141,6 @@
     @Mock
     private SettingsActivity mSettingsActivity;
 
-    private TextView mBatteryPercentText;
     private List<BatterySipper> mUsageList;
     private Context mRealContext;
     private TestFragment mFragment;
@@ -164,7 +164,7 @@
         mLastFullChargePref = new PowerGaugePreference(mRealContext);
         mFragment = spy(new TestFragment(mContext));
         mFragment.initFeatureProvider();
-        mBatteryMeterView = spy(new BatteryMeterView(mRealContext));
+        mBatteryMeterView = new BatteryMeterView(mRealContext);
         mBatteryMeterView.mDrawable = new BatteryMeterView.BatteryMeterDrawable(mRealContext, 0);
         doNothing().when(mFragment).restartBatteryStatsLoader();
 
@@ -187,7 +187,6 @@
         mCellBatterySipper.drainType = BatterySipper.DrainType.CELL;
         mCellBatterySipper.totalPowerMah = POWER_MAH;
 
-        mBatteryPercentText = new TextView(mRealContext);
         when(mBatteryLayoutPref.findViewById(R.id.summary1)).thenReturn(mSummary1);
         when(mBatteryLayoutPref.findViewById(R.id.battery_percent)).thenReturn(mBatteryPercentText);
         when(mBatteryLayoutPref.findViewById(R.id.battery_header_icon))
@@ -281,50 +280,6 @@
     }
 
     @Test
-    public void testInitHeaderPreference_initCorrectly() {
-        mFragment.mBatteryLevel = 100;
-
-        mFragment.initHeaderPreference();
-
-        assertThat(mBatteryMeterView.getBatteryLevel()).isEqualTo(100);
-        assertThat(mBatteryPercentText.getText().toString()).isEqualTo("100%");
-    }
-
-    @Test
-    public void testStartBatteryHeaderAnimationIfNecessary_batteryLevelChanged_animationStarted() {
-        final int prevLevel = 100;
-        final int curLevel = 80;
-
-        mFragment.startBatteryHeaderAnimationIfNecessary(mBatteryMeterView, mBatteryPercentText,
-                prevLevel, curLevel);
-
-        assertThat(mBatteryMeterView.getBatteryLevel()).isEqualTo(curLevel);
-        assertThat(mBatteryPercentText.getText().toString()).isEqualTo("80%");
-    }
-
-    @Test
-    public void testOnSaveInstanceState_saveBatteryLevel() {
-        Bundle bundle = new Bundle();
-        mFragment.mBatteryLevel = BATTERY_LEVEL;
-        // mock it to stop crash in getPreferenceScreen
-        doReturn(null).when(mFragment).getPreferenceScreen();
-
-        mFragment.onSaveInstanceState(bundle);
-
-        assertThat(bundle.getInt(PowerUsageSummary.ARG_BATTERY_LEVEL)).isEqualTo(BATTERY_LEVEL);
-    }
-
-    @Test
-    public void testOnActivityCreated_setBatteryLevel() {
-        Bundle bundle = new Bundle();
-        bundle.putInt(PowerUsageSummary.ARG_BATTERY_LEVEL, BATTERY_LEVEL);
-
-        mFragment.onActivityCreated(bundle);
-
-        assertThat(mFragment.mBatteryLevel).isEqualTo(BATTERY_LEVEL);
-    }
-
-    @Test
     public void testExtractKeyFromSipper_typeAPPUidObjectNull_returnPackageNames() {
         mNormalBatterySipper.uidObj = null;
         mNormalBatterySipper.drainType = BatterySipper.DrainType.APP;