Merge "API for notification listener for Companioon apps" into oc-dev
diff --git a/res/drawable/ic_media_stream_on_24dp.xml b/res/drawable/ic_media_stream_on_24dp.xml
new file mode 100644
index 0000000..3db55dd
--- /dev/null
+++ b/res/drawable/ic_media_stream_on_24dp.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2017 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M18,3h-5c-0.55,0 -1,0.45 -1,1v8.3a3.88,3.88 0,0 0,-2.9 -0.04c-1.79,0.67 -3.11,2.35 -3.1,4.26A4.483,4.483 0,0 0,10.5 21c2.5,0 4.5,-2.3 4.5,-4.5V6h3c0.55,0 1,-0.45 1,-1V4c0,-0.55 -0.45,-1 -1,-1z"/>
+</vector>
diff --git a/res/layout/storage_item.xml b/res/layout/storage_item.xml
index 33f4f9e..0c1f60c 100644
--- a/res/layout/storage_item.xml
+++ b/res/layout/storage_item.xml
@@ -76,6 +76,7 @@
         android:id="@android:id/progress"
         android:layout_width="match_parent"
         android:layout_height="8dp"
+        android:layout_marginStart="60dp"
         android:layout_marginTop="16dp"
         android:layout_marginBottom="8dp"
         android:visibility="gone"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index dea40b6..36643d3 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -4686,9 +4686,9 @@
     <string name="battery_last_full_charge">Last full charge</string>
     <!-- Description for text in battery footer. [CHAR LIMIT=120] -->
     <string name="battery_footer_summary">Remaining battery time is approximate and can change based on usage</string>
-    <!-- Title for battery usage detail in foreground. [CHAR LIMIT=80] -->
+    <!-- Title for text that shows the amount of time an app has been running while in the foreground. [CHAR LIMIT=80] -->
     <string name="battery_detail_foreground">While in active use</string>
-    <!-- Title for battery usage detail in background. [CHAR LIMIT=80] -->
+    <!-- Title for text that shows the amount of time an app has been running while in the background. [CHAR LIMIT=80] -->
     <string name="battery_detail_background">While in background</string>
     <!-- Title for battery usage amount by this app. [CHAR LIMIT=80] -->
     <string name="battery_detail_power_usage">Battery usage</string>
diff --git a/res/xml/app_memory_settings.xml b/res/xml/app_memory_settings.xml
index 53a71ff..308f189 100644
--- a/res/xml/app_memory_settings.xml
+++ b/res/xml/app_memory_settings.xml
@@ -18,26 +18,25 @@
                   android:title="@string/memory_usage">
 
     <PreferenceCategory
-        android:title="@string/average_memory_use"/>
+        android:title="@string/average_memory_use">
 
-    <com.android.settings.SummaryPreference
-        android:key="status_header"
-        android:selectable="false" />
+        <com.android.settings.SummaryPreference
+            android:key="status_header"
+            android:selectable="false" />
 
-    <com.android.settings.applications.SpacePreference
-        android:layout_height="5dp" />
+        <Preference
+            android:key="frequency"
+            android:selectable="false"
+            android:layout="@layout/horizontal_preference"
+            android:title="@string/running_frequency" />
 
-    <Preference
-        android:key="frequency"
-        android:selectable="false"
-        android:layout="@layout/horizontal_preference"
-        android:title="@string/running_frequency" />
+        <Preference
+            android:key="max_usage"
+            android:selectable="false"
+            android:layout="@layout/horizontal_preference"
+            android:title="@string/memory_maximum_usage" />
 
-    <Preference
-        android:key="max_usage"
-        android:selectable="false"
-        android:layout="@layout/horizontal_preference"
-        android:title="@string/memory_maximum_usage" />
+    </PreferenceCategory>
 
     <PreferenceCategory
         android:key="processes"
diff --git a/res/xml/app_storage_settings.xml b/res/xml/app_storage_settings.xml
index 6bd8ae3..1c71bfa 100644
--- a/res/xml/app_storage_settings.xml
+++ b/res/xml/app_storage_settings.xml
@@ -15,8 +15,14 @@
 -->
 
 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+                  xmlns:settings="http://schemas.android.com/apk/res-auto"
                   android:title="@string/application_info_label">
 
+    <com.android.settings.applications.LayoutPreference
+        android:key="header_view"
+        android:layout="@layout/app_action_buttons"
+        android:selectable="false" />
+
     <com.android.settings.applications.SpacePreference
         android:key="storage_space"
         android:layout_height="8dp" />
@@ -36,13 +42,9 @@
     <PreferenceCategory
         android:key="storage_category"
         android:layout="@layout/tall_preference_category"
-        android:title="@string/storage_label">
-
-        <Preference
-            android:key="total_size"
-            android:title="@string/total_size_label"
-            android:selectable="false"
-            android:layout="@layout/horizontal_preference" />
+        android:title="@string/app_info_storage_title"
+        settings:allowDividerAbove="false"
+        settings:allowDividerBelow="false">
 
         <Preference
             android:key="app_size"
@@ -56,32 +58,28 @@
             android:selectable="false"
             android:layout="@layout/horizontal_preference" />
 
-        <com.android.settings.applications.LayoutPreference
-            android:key="clear_data_button"
+        <Preference
+            android:key="cache_size"
+            android:title="@string/cache_size_label"
             android:selectable="false"
-            android:layout="@layout/single_button_panel" />
+            android:layout="@layout/horizontal_preference" />
+
+        <Preference
+            android:key="total_size"
+            android:title="@string/total_size_label"
+            android:selectable="false"
+            android:layout="@layout/horizontal_preference" />
+
+        <com.android.settings.applications.SpacePreference
+            android:layout_height="8dp" />
+
     </PreferenceCategory>
 
-    <com.android.settings.applications.SpacePreference
-        android:layout_height="8dp" />
-
-    <Preference
-        android:key="cache_size"
-        android:title="@string/cache_size_label"
-        android:selectable="false"
-        android:layout="@layout/horizontal_preference" />
-
-    <com.android.settings.applications.LayoutPreference
-        android:key="clear_cache_button"
-        android:selectable="false"
-        android:layout="@layout/single_button_panel" />
-
-    <com.android.settings.applications.SpacePreference
-        android:layout_height="8dp" />
-
     <PreferenceCategory
         android:key="uri_category"
-        android:layout="@layout/headerless_preference_category" >
+        android:layout="@layout/headerless_preference_category"
+        settings:allowDividerAbove="false"
+        settings:allowDividerBelow="false">
         <com.android.settings.applications.LayoutPreference
             android:key="clear_uri_button"
             android:layout="@layout/single_button_panel"
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index 015af17..34990ec 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -83,7 +83,10 @@
 
     // Constants for state save/restore
     private static final String SAVE_KEY_CATEGORIES = ":settings:categories";
-    private static final String SAVE_KEY_SHOW_HOME_AS_UP = ":settings:show_home_as_up";
+    @VisibleForTesting
+    static final String SAVE_KEY_SHOW_HOME_AS_UP = ":settings:show_home_as_up";
+    @VisibleForTesting
+    static final String SAVE_KEY_SHOW_SEARCH = ":settings:show_search";
 
     /**
      * When starting this activity, the invoking Intent can contain this extra
@@ -192,8 +195,10 @@
 
     private Button mNextButton;
 
-    private boolean mDisplayHomeAsUpEnabled;
-    private boolean mDisplaySearch;
+    @VisibleForTesting
+    boolean mDisplayHomeAsUpEnabled;
+    @VisibleForTesting
+    boolean mDisplaySearch;
 
     private boolean mIsShowingDashboard;
     private boolean mIsShortcut;
@@ -230,7 +235,6 @@
         if (!mDisplaySearch) {
             return false;
         }
-
         mSearchFeatureProvider.setUpSearchMenu(menu, this);
         return true;
     }
@@ -513,12 +517,28 @@
     @Override
     protected void onSaveInstanceState(Bundle outState) {
         super.onSaveInstanceState(outState);
+        saveState(outState);
+    }
 
+    /**
+     * For testing purposes to avoid crashes from final variables in Activity's onSaveInstantState.
+     */
+    @VisibleForTesting
+    void saveState(Bundle outState) {
         if (mCategories.size() > 0) {
             outState.putParcelableArrayList(SAVE_KEY_CATEGORIES, mCategories);
         }
 
         outState.putBoolean(SAVE_KEY_SHOW_HOME_AS_UP, mDisplayHomeAsUpEnabled);
+        outState.putBoolean(SAVE_KEY_SHOW_SEARCH, mDisplaySearch);
+    }
+
+    @Override
+    protected void onRestoreInstanceState(Bundle savedInstanceState) {
+        super.onRestoreInstanceState(savedInstanceState);
+
+        mDisplayHomeAsUpEnabled = savedInstanceState.getBoolean(SAVE_KEY_SHOW_HOME_AS_UP);
+        mDisplaySearch = savedInstanceState.getBoolean(SAVE_KEY_SHOW_SEARCH);
     }
 
     @Override
diff --git a/src/com/android/settings/applications/AppStorageSettings.java b/src/com/android/settings/applications/AppStorageSettings.java
index 8d41558..0676f56 100644
--- a/src/com/android/settings/applications/AppStorageSettings.java
+++ b/src/com/android/settings/applications/AppStorageSettings.java
@@ -90,13 +90,10 @@
 
     private static final String KEY_TOTAL_SIZE = "total_size";
     private static final String KEY_APP_SIZE = "app_size";
-    private static final String KEY_EXTERNAL_CODE_SIZE = "external_code_size";
     private static final String KEY_DATA_SIZE = "data_size";
-    private static final String KEY_EXTERNAL_DATA_SIZE = "external_data_size";
     private static final String KEY_CACHE_SIZE = "cache_size";
 
-    private static final String KEY_CLEAR_DATA = "clear_data_button";
-    private static final String KEY_CLEAR_CACHE = "clear_cache_button";
+    private static final String KEY_HEADER_BUTTONS = "header_view";
 
     private static final String KEY_URI_CATEGORY = "uri_category";
     private static final String KEY_CLEAR_URI = "clear_uri_button";
@@ -119,16 +116,11 @@
     private boolean mCanClearData = true;
     private boolean mCacheCleared;
 
-    private AppStorageStats mLastResult;
     private AppStorageSizesController mSizeController;
 
     private ClearCacheObserver mClearCacheObserver;
     private ClearUserDataObserver mClearDataObserver;
 
-    // Resource strings
-    private CharSequence mInvalidSizeStr;
-    private CharSequence mComputingStr;
-
     private VolumeInfo[] mCandidates;
     private AlertDialog.Builder mDialogBuilder;
     private ApplicationInfo mInfo;
@@ -158,9 +150,6 @@
     }
 
     private void setupViews() {
-        mComputingStr = getActivity().getText(R.string.computing_size);
-        mInvalidSizeStr = getActivity().getText(R.string.invalid_size_value);
-
         // Set default values on sizes
         mSizeController = new AppStorageSizesController.Builder()
                 .setTotalSizePreference(findPreference(KEY_TOTAL_SIZE))
@@ -171,8 +160,8 @@
                 .setErrorString(R.string.invalid_size_value)
                 .build();
 
-        mClearDataButton = (Button) ((LayoutPreference) findPreference(KEY_CLEAR_DATA))
-                .findViewById(R.id.button);
+        mClearDataButton = (Button) ((LayoutPreference) findPreference(KEY_HEADER_BUTTONS))
+                .findViewById(R.id.left_button);
 
         mStorageUsed = findPreference(KEY_STORAGE_USED);
         mChangeStorageButton = (Button) ((LayoutPreference) findPreference(KEY_CHANGE_STORAGE))
@@ -182,8 +171,8 @@
 
         // Cache section
         mCacheSize = findPreference(KEY_CACHE_SIZE);
-        mClearCacheButton = (Button) ((LayoutPreference) findPreference(KEY_CLEAR_CACHE))
-                .findViewById(R.id.button);
+        mClearCacheButton = (Button) ((LayoutPreference) findPreference(KEY_HEADER_BUTTONS))
+                .findViewById(R.id.right_button);
         mClearCacheButton.setText(R.string.clear_cache_btn_text);
 
         // URI permissions section
@@ -267,7 +256,7 @@
         if (mAppEntry == null) {
             return false;
         }
-        updateUiWithSize(mLastResult);
+        updateUiWithSize(mSizeController.getLastResult());
         refreshGrantedUriPermissions();
 
         final VolumeInfo currentVol = getActivity().getPackageManager()
diff --git a/src/com/android/settings/applications/AppStorageSizesController.java b/src/com/android/settings/applications/AppStorageSizesController.java
index 94935bd..23a3eb2 100644
--- a/src/com/android/settings/applications/AppStorageSizesController.java
+++ b/src/com/android/settings/applications/AppStorageSizesController.java
@@ -110,6 +110,13 @@
         mCachedCleared = isCleared;
     }
 
+    /**
+     * Returns the last result calculated, if it exists. If it does not, returns null.
+     */
+    public StorageStatsSource.AppStorageStats getLastResult() {
+        return mLastResult;
+    }
+
     private String getSizeStr(Context context, long size) {
         return Formatter.formatFileSize(context, size);
     }
diff --git a/src/com/android/settings/applications/MusicViewHolderController.java b/src/com/android/settings/applications/MusicViewHolderController.java
index 4599fcc..69f8958 100644
--- a/src/com/android/settings/applications/MusicViewHolderController.java
+++ b/src/com/android/settings/applications/MusicViewHolderController.java
@@ -61,7 +61,7 @@
 
     @Override
     public void setupView(AppViewHolder holder) {
-        holder.appIcon.setImageDrawable(mContext.getDrawable(R.drawable.empty_icon));
+        holder.appIcon.setImageDrawable(mContext.getDrawable(R.drawable.ic_media_stream_on_24dp));
         holder.appName.setText(mContext.getText(R.string.audio_files_title));
         holder.summary.setText(Formatter.formatFileSize(mContext, mMusicSize));
     }
diff --git a/src/com/android/settings/applications/assist/DefaultAssistPreferenceController.java b/src/com/android/settings/applications/assist/DefaultAssistPreferenceController.java
index 747ce4d..b8d6a87 100644
--- a/src/com/android/settings/applications/assist/DefaultAssistPreferenceController.java
+++ b/src/com/android/settings/applications/assist/DefaultAssistPreferenceController.java
@@ -24,6 +24,7 @@
 import android.service.voice.VoiceInteractionService;
 import android.service.voice.VoiceInteractionServiceInfo;
 
+import android.support.annotation.VisibleForTesting;
 import com.android.internal.app.AssistUtils;
 import com.android.settings.applications.defaultapps.DefaultAppInfo;
 import com.android.settings.applications.defaultapps.DefaultAppPreferenceController;
@@ -56,13 +57,10 @@
         if (services == null || services.isEmpty()) {
             return null;
         }
-        final ResolveInfo resolveInfo = services.get(0);
-        final VoiceInteractionServiceInfo voiceInfo =
-                new VoiceInteractionServiceInfo(pm, resolveInfo.serviceInfo);
-        if (!voiceInfo.getSupportsAssist()) {
+        final String activity = getAssistSettingsActivity(cn, services.get(0), pm);
+        if (activity == null) {
             return null;
         }
-        final String activity = voiceInfo.getSettingsActivity();
         return new Intent(Intent.ACTION_MAIN)
                 .setComponent(new ComponentName(cn.getPackageName(), activity));
     }
@@ -85,4 +83,14 @@
         }
         return new DefaultAppInfo(mPackageManager, mUserId, cn);
     }
+
+    @VisibleForTesting
+    String getAssistSettingsActivity(ComponentName cn, ResolveInfo resolveInfo, PackageManager pm) {
+        final VoiceInteractionServiceInfo voiceInfo =
+            new VoiceInteractionServiceInfo(pm, resolveInfo.serviceInfo);
+        if (!voiceInfo.getSupportsAssist()) {
+            return null;
+        }
+        return voiceInfo.getSettingsActivity();
+    }
 }
diff --git a/src/com/android/settings/deviceinfo/StorageDashboardFragment.java b/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
index 602e65f..bc64ffa 100644
--- a/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
+++ b/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
@@ -117,7 +117,7 @@
     @Override
     public void onResume() {
         super.onResume();
-        getLoaderManager().initLoader(STORAGE_JOB_ID, Bundle.EMPTY, this);
+        getLoaderManager().restartLoader(STORAGE_JOB_ID, Bundle.EMPTY, this);
         getLoaderManager().initLoader(ICON_JOB_ID, Bundle.EMPTY, new IconLoaderCallbacks());
     }
 
diff --git a/src/com/android/settings/deviceinfo/storage/StorageAsyncLoader.java b/src/com/android/settings/deviceinfo/storage/StorageAsyncLoader.java
index e83c5d2..cf0239d 100644
--- a/src/com/android/settings/deviceinfo/storage/StorageAsyncLoader.java
+++ b/src/com/android/settings/deviceinfo/storage/StorageAsyncLoader.java
@@ -79,8 +79,15 @@
         UserHandle myUser = UserHandle.of(userId);
         for (int i = 0, size = applicationInfos.size(); i < size; i++) {
             ApplicationInfo app = applicationInfos.get(i);
-            StorageStatsSource.AppStorageStats stats =
-                    mStatsManager.getStatsForPackage(mUuid, app.packageName, myUser);
+
+            StorageStatsSource.AppStorageStats stats;
+            try {
+                stats = mStatsManager.getStatsForPackage(mUuid, app.packageName, myUser);
+            } catch (IllegalStateException e) {
+                // This may happen if the package was removed during our calculation.
+                Log.w("App unexpectedly not found", e);
+                continue;
+            }
 
             long attributedAppSizeInBytes = stats.getDataBytes();
             // This matches how the package manager calculates sizes -- by zeroing out code sizes of
diff --git a/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java b/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java
index 3509834..a0ebba8 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java
@@ -172,7 +172,7 @@
         mUsageListGroup.removeAll();
         for (int i = 0, size = dataList.size(); i < size; i++) {
             final PowerUsageData batteryData = dataList.get(i);
-            if (shouldHide(batteryData)) {
+            if (shouldHideCategory(batteryData)) {
                 continue;
             }
             final PowerGaugePreference pref = new PowerGaugePreference(getPrefContext());
@@ -217,7 +217,7 @@
     }
 
     @VisibleForTesting
-    boolean shouldHide(PowerUsageData powerUsageData) {
+    boolean shouldHideCategory(PowerUsageData powerUsageData) {
         if (powerUsageData.usageType == UsageType.UNACCOUNTED
                 || powerUsageData.usageType == UsageType.OVERCOUNTED) {
             return true;
@@ -264,6 +264,9 @@
 
     @VisibleForTesting
     void updateUsageDataSummary(PowerUsageData usageData, double totalPower, int dischargeAmount) {
+        if (shouldHideSummary(usageData)) {
+            return;
+        }
         if (usageData.usageList.size() <= 1) {
             usageData.summary = getString(R.string.battery_used_for,
                     Utils.formatElapsedTime(getContext(), usageData.totalUsageTimeMs, false));
@@ -278,6 +281,13 @@
     }
 
     @VisibleForTesting
+    boolean shouldHideSummary(PowerUsageData powerUsageData) {
+        @UsageType final int usageType = powerUsageData.usageType;
+
+        return usageType == UsageType.CELL;
+    }
+
+    @VisibleForTesting
     BatterySipper findBatterySipperWithMaxBatteryUsage(List<BatterySipper> usageList) {
         BatterySipper sipper = usageList.get(0);
         for (int i = 1, size = usageList.size(); i < size; i++) {
diff --git a/src/com/android/settings/network/NetworkResetActionMenuController.java b/src/com/android/settings/network/NetworkResetActionMenuController.java
index 028ac7b..254834b 100644
--- a/src/com/android/settings/network/NetworkResetActionMenuController.java
+++ b/src/com/android/settings/network/NetworkResetActionMenuController.java
@@ -17,9 +17,6 @@
 package com.android.settings.network;
 
 import android.content.Context;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.support.annotation.VisibleForTesting;
 import android.view.Menu;
 import android.view.MenuItem;
 
@@ -27,15 +24,16 @@
 import com.android.settings.R;
 import com.android.settings.ResetNetwork;
 import com.android.settings.Utils;
-import com.android.settingslib.RestrictedLockUtils;
 
 public class NetworkResetActionMenuController {
 
     private static final int MENU_NETWORK_RESET = Menu.FIRST + 200;
     private final Context mContext;
+    private final NetworkResetRestrictionChecker mRestrictionChecker;
 
     public NetworkResetActionMenuController(Context context) {
         mContext = context;
+        mRestrictionChecker = new NetworkResetRestrictionChecker(context);
     }
 
     public void buildMenuItem(Menu menu) {
@@ -53,14 +51,8 @@
         }
     }
 
-    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+
     boolean isAvailable() {
-        return isAvailable(mContext);
+        return !mRestrictionChecker.hasRestriction();
     }
-
-    static boolean isAvailable(Context context) {
-        return !RestrictedLockUtils.hasBaseUserRestriction(context,
-                UserManager.DISALLOW_NETWORK_RESET, UserHandle.myUserId());
-    }
-
 }
diff --git a/src/com/android/settings/network/NetworkResetPreferenceController.java b/src/com/android/settings/network/NetworkResetPreferenceController.java
index 04573c9..ce36a7f 100644
--- a/src/com/android/settings/network/NetworkResetPreferenceController.java
+++ b/src/com/android/settings/network/NetworkResetPreferenceController.java
@@ -22,13 +22,16 @@
 
 public class NetworkResetPreferenceController extends PreferenceController {
 
+    private final NetworkResetRestrictionChecker mRestrictionChecker;
+
     public NetworkResetPreferenceController(Context context) {
         super(context);
+        mRestrictionChecker = new NetworkResetRestrictionChecker(context);
     }
 
     @Override
     public boolean isAvailable() {
-        return NetworkResetActionMenuController.isAvailable(mContext);
+        return !mRestrictionChecker.hasRestriction();
     }
 
     @Override
diff --git a/src/com/android/settings/network/NetworkResetRestrictionChecker.java b/src/com/android/settings/network/NetworkResetRestrictionChecker.java
new file mode 100644
index 0000000..4fe9f59
--- /dev/null
+++ b/src/com/android/settings/network/NetworkResetRestrictionChecker.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network;
+
+import android.content.Context;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.support.annotation.VisibleForTesting;
+
+import com.android.settingslib.RestrictedLockUtils;
+
+public class NetworkResetRestrictionChecker {
+
+    private final Context mContext;
+    private final UserManager mUserManager;
+
+    public NetworkResetRestrictionChecker(Context context) {
+        mContext = context;
+        mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+    }
+
+    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+    boolean hasUserBaseRestriction() {
+        return RestrictedLockUtils.hasBaseUserRestriction(mContext,
+                UserManager.DISALLOW_NETWORK_RESET, UserHandle.myUserId());
+    }
+
+    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+    boolean isRestrictionEnforcedByAdmin() {
+        return RestrictedLockUtils.checkIfRestrictionEnforced(
+                mContext, UserManager.DISALLOW_NETWORK_RESET, UserHandle.myUserId()) != null;
+    }
+
+    boolean hasRestriction() {
+        return !mUserManager.isAdminUser()
+                || hasUserBaseRestriction()
+                || isRestrictionEnforcedByAdmin();
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/SettingsActivityTest.java b/tests/robotests/src/com/android/settings/SettingsActivityTest.java
index 9d53bc8..65e9708 100644
--- a/tests/robotests/src/com/android/settings/SettingsActivityTest.java
+++ b/tests/robotests/src/com/android/settings/SettingsActivityTest.java
@@ -16,20 +16,28 @@
 
 package com.android.settings;
 
+import android.app.Activity;
 import android.app.ActivityManager;
 import android.app.FragmentManager;
 import android.app.FragmentTransaction;
+import android.content.Context;
 import android.content.Intent;
 import android.graphics.Bitmap;
 
+import android.os.Bundle;
+import android.view.Menu;
+import com.android.settings.testutils.FakeFeatureFactory;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Answers;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
+import org.robolectric.util.ReflectionHelpers;
 
+import static com.google.common.truth.Truth.assertThat;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Mockito.doReturn;
@@ -42,6 +50,9 @@
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class SettingsActivityTest {
 
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private Context mContext;
+
     @Mock
     private FragmentManager mFragmentManager;
     @Mock
@@ -50,10 +61,15 @@
     private Bitmap mBitmap;
     private SettingsActivity mActivity;
 
+    private FakeFeatureFactory mFeatureFactory;
+
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
 
+        FakeFeatureFactory.setupForTest(mContext);
+        mFeatureFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
+
         mActivity = spy(new SettingsActivity());
         doReturn(mBitmap).when(mActivity).getBitmapFromXmlResource(anyInt());
     }
@@ -61,7 +77,6 @@
     @Test
     public void launchSettingFragment_nullExtraShowFragment_shouldNotCrash()
             throws ClassNotFoundException {
-        mActivity = spy(new SettingsActivity());
         when(mActivity.getFragmentManager()).thenReturn(mFragmentManager);
         when(mFragmentManager.beginTransaction()).thenReturn(mock(FragmentTransaction.class));
 
@@ -76,4 +91,51 @@
 
         verify(mTaskDescription).setIcon(any());
     }
+
+    @Test
+    public void testCreateOptionsMenu_setsUpSearch() {
+        ReflectionHelpers.setField(mActivity, "mSearchFeatureProvider",
+                mFeatureFactory.getSearchFeatureProvider());
+        mActivity.mDisplaySearch = true;
+        mActivity.onCreateOptionsMenu(null);
+
+        verify(mFeatureFactory.getSearchFeatureProvider()).setUpSearchMenu(any(Menu.class),
+                any(Activity.class));
+    }
+
+    @Test
+    public void testSaveState_DisplaySearchSaved() {
+        mActivity.mDisplaySearch = true;
+        Bundle bundle = new Bundle();
+        mActivity.saveState(bundle);
+
+        assertThat((boolean) bundle.get(SettingsActivity.SAVE_KEY_SHOW_SEARCH)).isTrue();
+    }
+
+    @Test
+    public void testSaveState_EnabledHomeSaved() {
+        mActivity.mDisplayHomeAsUpEnabled = true;
+        Bundle bundle = new Bundle();
+        mActivity.saveState(bundle);
+
+        assertThat((boolean) bundle.get(SettingsActivity.SAVE_KEY_SHOW_HOME_AS_UP)).isTrue();
+    }
+
+    @Test
+    public void testRestoreState_DisplaySearchRestored() {
+        Bundle bundle = new Bundle();
+        bundle.putBoolean(SettingsActivity.SAVE_KEY_SHOW_SEARCH, true);
+        mActivity.onRestoreInstanceState(bundle);
+
+        assertThat(mActivity.mDisplaySearch).isTrue();
+    }
+
+    @Test
+    public void testRestoreState_EnabledHomeRestored() {
+        Bundle bundle = new Bundle();
+        bundle.putBoolean(SettingsActivity.SAVE_KEY_SHOW_SEARCH, true);
+        mActivity.onRestoreInstanceState(bundle);
+
+        assertThat(mActivity.mDisplaySearch).isTrue();
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/applications/assist/DefaultAssistPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/assist/DefaultAssistPreferenceControllerTest.java
index 1182762..728a8a5 100644
--- a/tests/robotests/src/com/android/settings/applications/assist/DefaultAssistPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/assist/DefaultAssistPreferenceControllerTest.java
@@ -16,7 +16,16 @@
 
 package com.android.settings.applications.assist;
 
+import android.Manifest;
+import android.app.SearchManager;
+import android.content.ComponentName;
 import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
 import android.provider.Settings;
 
 import com.android.settings.SettingsRobolectricTestRunner;
@@ -24,6 +33,8 @@
 import com.android.settings.applications.defaultapps.DefaultAppInfo;
 import com.android.settings.testutils.shadow.ShadowSecureSettings;
 
+import java.util.ArrayList;
+import java.util.List;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -32,6 +43,13 @@
 import org.robolectric.annotation.Config;
 
 import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
 
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
@@ -39,6 +57,10 @@
 
     @Mock
     private Context mContext;
+    @Mock
+    private SearchManager mSearchManager;
+    @Mock
+    private PackageManager mPackageManager;
     private DefaultAssistPreferenceController mController;
 
     @Before
@@ -61,4 +83,33 @@
 
         assertThat(appInfo.getKey()).isEqualTo(flattenKey);
     }
+
+    @Test
+    public void getSettingIntent_noSettingsActivity_shouldNotCrash() {
+        final String flattenKey = "com.android.settings/assist";
+        ShadowSecureSettings.putString(null, Settings.Secure.ASSISTANT, flattenKey);
+        when(mContext.getPackageManager()).thenReturn(mPackageManager);
+        DefaultAssistPreferenceController controller =
+            spy(new DefaultAssistPreferenceController(mContext));
+        final ResolveInfo resolveInfo = new ResolveInfo();
+        resolveInfo.activityInfo = new ActivityInfo();
+        resolveInfo.activityInfo.name = "assist";
+        resolveInfo.activityInfo.applicationInfo = new ApplicationInfo();
+        resolveInfo.activityInfo.applicationInfo.packageName = "com.android.settings";
+        when(mPackageManager.resolveActivityAsUser(any(Intent.class), anyInt(), anyInt()))
+            .thenReturn(resolveInfo);
+        when(mContext.getSystemService(Context.SEARCH_SERVICE)).thenReturn(mSearchManager);
+        when(mSearchManager.getAssistIntent(anyBoolean())).thenReturn(mock(Intent.class));
+        final ServiceInfo serviceInfo = new ServiceInfo();
+        serviceInfo.permission = Manifest.permission.BIND_VOICE_INTERACTION;
+        resolveInfo.serviceInfo = serviceInfo;
+        final List<ResolveInfo> services = new ArrayList<>();
+        services.add(resolveInfo);
+        when(mPackageManager.queryIntentServices(any(Intent.class), anyInt())).thenReturn(services);
+        doReturn(null).when(controller).getAssistSettingsActivity(
+            ComponentName.unflattenFromString(flattenKey), resolveInfo, mPackageManager);
+
+        controller.getSettingIntent(null);
+        // should not crash
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageAdvancedTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageAdvancedTest.java
index 4216d57..3f87bb4 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageAdvancedTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageAdvancedTest.java
@@ -228,22 +228,36 @@
     public void testShouldHide_typeUnAccounted_returnTrue() {
         mPowerUsageData.usageType = UsageType.UNACCOUNTED;
 
-        assertThat(mPowerUsageAdvanced.shouldHide(mPowerUsageData)).isTrue();
+        assertThat(mPowerUsageAdvanced.shouldHideCategory(mPowerUsageData)).isTrue();
     }
 
 
     @Test
-    public void testShouldHide_typeOverCounted_returnTrue() {
+    public void testShouldHideCategory_typeOverCounted_returnTrue() {
         mPowerUsageData.usageType = UsageType.OVERCOUNTED;
 
-        assertThat(mPowerUsageAdvanced.shouldHide(mPowerUsageData)).isTrue();
+        assertThat(mPowerUsageAdvanced.shouldHideCategory(mPowerUsageData)).isTrue();
     }
 
-
     @Test
-    public void testShouldHide_typeNormal_returnFalse() {
+    public void testShouldHideCategory_typeNormal_returnFalse() {
         mPowerUsageData.usageType = UsageType.APP;
 
-        assertThat(mPowerUsageAdvanced.shouldHide(mPowerUsageData)).isFalse();
+        assertThat(mPowerUsageAdvanced.shouldHideCategory(mPowerUsageData)).isFalse();
     }
+
+    @Test
+    public void testShouldHideSummary_typeCell_returnTrue() {
+        mPowerUsageData.usageType = UsageType.CELL;
+
+        assertThat(mPowerUsageAdvanced.shouldHideSummary(mPowerUsageData)).isTrue();
+    }
+
+    @Test
+    public void testShouldHideSummary_typeNormal_returnFalse() {
+        mPowerUsageData.usageType = UsageType.APP;
+
+        assertThat(mPowerUsageAdvanced.shouldHideSummary(mPowerUsageData)).isFalse();
+    }
+
 }
diff --git a/tests/robotests/src/com/android/settings/network/NetworkResetActionMenuControllerTest.java b/tests/robotests/src/com/android/settings/network/NetworkResetActionMenuControllerTest.java
index 7cd76d3..ee6ef69 100644
--- a/tests/robotests/src/com/android/settings/network/NetworkResetActionMenuControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/NetworkResetActionMenuControllerTest.java
@@ -19,9 +19,7 @@
 
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyInt;
-import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -39,6 +37,7 @@
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
+import org.robolectric.util.ReflectionHelpers;
 
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
@@ -50,19 +49,21 @@
     private Menu mMenu;
     @Mock
     private MenuItem mMenuItem;
+    @Mock
+    private NetworkResetRestrictionChecker mRestrictionChecker;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         mContext = RuntimeEnvironment.application;
-        mController = spy(new NetworkResetActionMenuController(mContext));
+        mController = new NetworkResetActionMenuController(mContext);
+        ReflectionHelpers.setField(mController, "mRestrictionChecker", mRestrictionChecker);
         when(mMenu.add(anyInt(), anyInt(), anyInt(), anyInt())).thenReturn(mMenuItem);
     }
 
     @Test
     public void buildMenuItem_available_shouldAddToMenu() {
-        doReturn(true).when(mController).isAvailable();
-
+        when(mRestrictionChecker.hasRestriction()).thenReturn(false);
         mController.buildMenuItem(mMenu);
 
         verify(mMenu).add(anyInt(), anyInt(), anyInt(), anyInt());
@@ -71,7 +72,7 @@
 
     @Test
     public void buildMenuItem_notAvailable_shouldNotAddToMenu() {
-        doReturn(false).when(mController).isAvailable();
+        when(mRestrictionChecker.hasRestriction()).thenReturn(true);
 
         mController.buildMenuItem(mMenu);
 
diff --git a/tests/robotests/src/com/android/settings/network/NetworkResetRestrictionCheckerTest.java b/tests/robotests/src/com/android/settings/network/NetworkResetRestrictionCheckerTest.java
new file mode 100644
index 0000000..b1c88d5
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/network/NetworkResetRestrictionCheckerTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.os.UserManager;
+
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class NetworkResetRestrictionCheckerTest {
+
+    @Mock
+    private UserManager mUserManager;
+    @Mock
+    private Context mContext;
+    private NetworkResetRestrictionChecker mRestrictionChecker;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
+        mRestrictionChecker = spy(new NetworkResetRestrictionChecker(mContext));
+    }
+
+    @Test
+    public void testHasRestriction_notAdmin_shouldReturnTrue() {
+        final Context context = mock(Context.class);
+        when(context.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
+        when(mUserManager.isAdminUser()).thenReturn(false);
+
+        assertThat(mRestrictionChecker.hasRestriction()).isTrue();
+    }
+
+    @Test
+    public void testHasRestriction_hasUserRestriction_shouldReturnTrue() {
+        when(mUserManager.isAdminUser()).thenReturn(true);
+        doReturn(true).when(mRestrictionChecker).hasUserBaseRestriction();
+        doReturn(false).when(mRestrictionChecker).isRestrictionEnforcedByAdmin();
+
+        assertThat(mRestrictionChecker.hasRestriction()).isTrue();
+    }
+
+    @Test
+    public void testHasRestriction_hasAdminRestriction_shouldReturnTrue() {
+        when(mUserManager.isAdminUser()).thenReturn(true);
+        doReturn(false).when(mRestrictionChecker).hasUserBaseRestriction();
+        doReturn(true).when(mRestrictionChecker).isRestrictionEnforcedByAdmin();
+
+        assertThat(mRestrictionChecker.hasRestriction()).isTrue();
+    }
+
+    @Test
+    public void testHasRestriction_noRestriction_shouldReturnFalse() {
+        when(mUserManager.isAdminUser()).thenReturn(true);
+        doReturn(false).when(mRestrictionChecker).hasUserBaseRestriction();
+        doReturn(false).when(mRestrictionChecker).isRestrictionEnforcedByAdmin();
+
+        assertThat(mRestrictionChecker.hasRestriction()).isFalse();
+    }
+}
diff --git a/tests/unit/src/com/android/settings/deviceinfo/storage/StorageAsyncLoaderTest.java b/tests/unit/src/com/android/settings/deviceinfo/storage/StorageAsyncLoaderTest.java
index e82482e..f7131b3 100644
--- a/tests/unit/src/com/android/settings/deviceinfo/storage/StorageAsyncLoaderTest.java
+++ b/tests/unit/src/com/android/settings/deviceinfo/storage/StorageAsyncLoaderTest.java
@@ -180,6 +180,20 @@
         assertThat(result.get(PRIMARY_USER_ID).otherAppsSize).isEqualTo(0);
     }
 
+    @Test
+    public void testRemovedPackageDoesNotCrash() throws Exception {
+        ApplicationInfo info = new ApplicationInfo();
+        info.packageName = PACKAGE_NAME_1;
+        info.category = ApplicationInfo.CATEGORY_UNDEFINED;
+        mInfo.add(info);
+        when(mSource.getStatsForPackage(anyString(), anyString(), any(UserHandle.class)))
+                .thenThrow(new IllegalStateException());
+
+        SparseArray<StorageAsyncLoader.AppsStorageResult> result = mLoader.loadInBackground();
+
+        // Should not crash.
+    }
+
     private ApplicationInfo addPackage(
             String packageName, long cacheSize, long codeSize, long dataSize, int category) {
         StorageStatsSource.AppStorageStats storageStats =