diff --git a/res/layout/dashboard_tile.xml b/res/layout/dashboard_tile.xml index d1625c7e68c..cc237eebdf9 100644 --- a/res/layout/dashboard_tile.xml +++ b/res/layout/dashboard_tile.xml @@ -59,7 +59,7 @@ diff --git a/res/values/strings.xml b/res/values/strings.xml index bba72c54a92..8c1bb83c908 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -7015,4 +7015,22 @@ See all See less + + + Disconnected + + + %1$s of data used + + + %1$d apps installed + + + %1$s of %2$s used + + + Adaptive brightness in ON + + + Adaptive brightness in OFF diff --git a/src/com/android/settings/DataUsageSummary.java b/src/com/android/settings/DataUsageSummary.java index bcd05bdef37..60eb17c1d9c 100644 --- a/src/com/android/settings/DataUsageSummary.java +++ b/src/com/android/settings/DataUsageSummary.java @@ -17,6 +17,7 @@ package com.android.settings; import android.animation.LayoutTransition; +import android.app.Activity; import android.app.ActivityManager; import android.app.AlertDialog; import android.app.Dialog; @@ -24,8 +25,6 @@ import android.app.DialogFragment; import android.app.Fragment; import android.app.FragmentTransaction; import android.app.LoaderManager.LoaderCallbacks; -import android.icu.impl.ICUResourceBundle; -import android.icu.util.UResourceBundle; import android.content.ComponentName; import android.content.Context; import android.content.DialogInterface; @@ -39,6 +38,8 @@ import android.content.res.Resources; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; +import android.icu.impl.ICUResourceBundle; +import android.icu.util.UResourceBundle; import android.net.ConnectivityManager; import android.net.INetworkPolicyManager; import android.net.INetworkStatsService; @@ -95,9 +96,9 @@ import android.widget.TabHost.TabSpec; import android.widget.TabWidget; import android.widget.TextView; import android.widget.Toast; - import com.android.internal.logging.MetricsLogger; import com.android.internal.telephony.PhoneConstants; +import com.android.settings.dashboard.SummaryLoader; import com.android.settings.drawable.InsetBoundsDrawable; import com.android.settings.net.DataUsageMeteredSettings; import com.android.settings.search.BaseSearchIndexProvider; @@ -110,11 +111,11 @@ import com.android.settingslib.AppItem; import com.android.settingslib.NetworkPolicyEditor; import com.android.settingslib.net.ChartData; import com.android.settingslib.net.ChartDataLoader; +import com.android.settingslib.net.MobileDataController; import com.android.settingslib.net.SummaryForAllUidLoader; import com.android.settingslib.net.UidDetail; import com.android.settingslib.net.UidDetailProvider; import com.google.android.collect.Lists; - import libcore.util.Objects; import java.util.ArrayList; @@ -2800,4 +2801,44 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable private boolean isMobileDataAvailable(int subId) { return mSubscriptionManager.getActiveSubscriptionInfo(subId) != null; } + + private static class SummaryProvider + implements SummaryLoader.SummaryProvider { + + private final Activity mActivity; + private final SummaryLoader mSummaryLoader; + private final MobileDataController mDataController; + + public SummaryProvider(Activity activity, SummaryLoader summaryLoader) { + mActivity = activity; + mSummaryLoader = summaryLoader; + mDataController = new MobileDataController(activity); + } + + @Override + public void setListening(boolean listening) { + if (listening) { + MobileDataController.DataUsageInfo info = mDataController.getDataUsageInfo(); + String used; + if (info == null) { + used = Formatter.formatFileSize(mActivity, 0); + } else if (info.limitLevel <= 0) { + used = Formatter.formatFileSize(mActivity, info.usageLevel); + } else { + used = Utils.formatPercentage(info.usageLevel, info.limitLevel); + } + mSummaryLoader.setSummary(this, + mActivity.getString(R.string.data_usage_summary_format, used)); + } + } + } + + public static final SummaryLoader.SummaryProviderFactory SUMMARY_PROVIDER_FACTORY + = new SummaryLoader.SummaryProviderFactory() { + @Override + public SummaryLoader.SummaryProvider createSummaryProvider(Activity activity, + SummaryLoader summaryLoader) { + return new SummaryProvider(activity, summaryLoader); + } + }; } diff --git a/src/com/android/settings/DisplaySettings.java b/src/com/android/settings/DisplaySettings.java index e26200a8263..0d52aa7fdf1 100644 --- a/src/com/android/settings/DisplaySettings.java +++ b/src/com/android/settings/DisplaySettings.java @@ -38,9 +38,9 @@ import android.support.v7.preference.Preference; import android.support.v7.preference.Preference.OnPreferenceChangeListener; import android.text.TextUtils; import android.util.Log; - import com.android.internal.logging.MetricsLogger; import com.android.internal.view.RotationPolicy; +import com.android.settings.dashboard.SummaryLoader; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.search.Indexable; @@ -481,6 +481,40 @@ public class DisplaySettings extends SettingsPreferenceFragment implements return R.string.help_uri_display; } + private static class SummaryProvider implements SummaryLoader.SummaryProvider { + private final Context mContext; + private final SummaryLoader mLoader; + + private SummaryProvider(Context context, SummaryLoader loader) { + mContext = context; + mLoader = loader; + } + + @Override + public void setListening(boolean listening) { + if (listening) { + updateSummary(); + } + } + + private void updateSummary() { + boolean auto = Settings.System.getInt(mContext.getContentResolver(), + SCREEN_BRIGHTNESS_MODE, SCREEN_BRIGHTNESS_MODE_AUTOMATIC) + == SCREEN_BRIGHTNESS_MODE_AUTOMATIC; + mLoader.setSummary(this, mContext.getString(auto ? R.string.display_summary_on + : R.string.display_summary_off)); + } + } + + public static final SummaryLoader.SummaryProviderFactory SUMMARY_PROVIDER_FACTORY + = new SummaryLoader.SummaryProviderFactory() { + @Override + public SummaryLoader.SummaryProvider createSummaryProvider(Activity activity, + SummaryLoader summaryLoader) { + return new SummaryProvider(activity, summaryLoader); + } + }; + public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = new BaseSearchIndexProvider() { @Override diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java index b0a112077ef..fd4a493fadb 100644 --- a/src/com/android/settings/SettingsActivity.java +++ b/src/com/android/settings/SettingsActivity.java @@ -189,7 +189,7 @@ public class SettingsActivity extends SettingsDrawerActivity public static final String EXTRA_SHOW_FRAGMENT_AS_SUBSETTING = ":settings:show_fragment_as_subsetting"; - private static final String META_DATA_KEY_FRAGMENT_CLASS = + public static final String META_DATA_KEY_FRAGMENT_CLASS = "com.android.settings.FRAGMENT_CLASS"; private static final String EXTRA_UI_OPTIONS = "settings:ui_options"; diff --git a/src/com/android/settings/applications/InstalledAppDetails.java b/src/com/android/settings/applications/InstalledAppDetails.java index dc09c45d32d..0b162cf180c 100755 --- a/src/com/android/settings/applications/InstalledAppDetails.java +++ b/src/com/android/settings/applications/InstalledAppDetails.java @@ -790,7 +790,7 @@ public class InstalledAppDetails extends AppInfoBase } } - private static NetworkTemplate getTemplate(Context context) { + public static NetworkTemplate getTemplate(Context context) { if (DataUsageSummary.hasReadyMobileRadio(context)) { return NetworkTemplate.buildTemplateMobileWildcard(); } diff --git a/src/com/android/settings/applications/ManageApplications.java b/src/com/android/settings/applications/ManageApplications.java index 8694ca90eec..b65d03b5a49 100644 --- a/src/com/android/settings/applications/ManageApplications.java +++ b/src/com/android/settings/applications/ManageApplications.java @@ -17,6 +17,7 @@ package com.android.settings.applications; import android.app.Activity; +import android.app.Application; import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; @@ -45,7 +46,6 @@ import android.widget.Filterable; import android.widget.FrameLayout; import android.widget.ListView; import android.widget.Spinner; - import com.android.internal.logging.MetricsLogger; import com.android.settings.AppHeader; import com.android.settings.HelpUtils; @@ -63,6 +63,7 @@ import com.android.settings.SettingsActivity; import com.android.settings.Utils; import com.android.settings.applications.AppStateAppOpsBridge.PermissionState; import com.android.settings.applications.AppStateUsageBridge.UsageState; +import com.android.settings.dashboard.SummaryLoader; import com.android.settings.fuelgauge.HighPowerDetail; import com.android.settings.fuelgauge.PowerWhitelistBackend; import com.android.settings.notification.AppNotificationSettings; @@ -113,60 +114,60 @@ public class ManageApplications extends InstrumentedFragment // Filter options used for displayed list of applications // The order which they appear is the order they will show when spinner is present. - public static final int FILTER_APPS_POWER_WHITELIST = 0; - public static final int FILTER_APPS_POWER_WHITELIST_ALL = 1; - public static final int FILTER_APPS_ALL = 2; - public static final int FILTER_APPS_ENABLED = 3; - public static final int FILTER_APPS_DISABLED = 4; - public static final int FILTER_APPS_BLOCKED = 5; - public static final int FILTER_APPS_PRIORITY = 6; - public static final int FILTER_APPS_NO_PEEKING = 7; - public static final int FILTER_APPS_SENSITIVE = 8; - public static final int FILTER_APPS_PERSONAL = 9; - public static final int FILTER_APPS_WORK = 10; - public static final int FILTER_APPS_WITH_DOMAIN_URLS = 11; - public static final int FILTER_APPS_USAGE_ACCESS = 12; - public static final int FILTER_APPS_WITH_OVERLAY = 13; - public static final int FILTER_APPS_WRITE_SETTINGS = 14; + public static final int FILTER_APPS_POWER_WHITELIST = 0; + public static final int FILTER_APPS_POWER_WHITELIST_ALL = 1; + public static final int FILTER_APPS_ALL = 2; + public static final int FILTER_APPS_ENABLED = 3; + public static final int FILTER_APPS_DISABLED = 4; + public static final int FILTER_APPS_BLOCKED = 5; + public static final int FILTER_APPS_PRIORITY = 6; + public static final int FILTER_APPS_NO_PEEKING = 7; + public static final int FILTER_APPS_SENSITIVE = 8; + public static final int FILTER_APPS_PERSONAL = 9; + public static final int FILTER_APPS_WORK = 10; + public static final int FILTER_APPS_WITH_DOMAIN_URLS = 11; + public static final int FILTER_APPS_USAGE_ACCESS = 12; + public static final int FILTER_APPS_WITH_OVERLAY = 13; + public static final int FILTER_APPS_WRITE_SETTINGS = 14; // This is the string labels for the filter modes above, the order must be kept in sync. - public static final int[] FILTER_LABELS = new int[] { - R.string.high_power_filter_on, // High power whitelist, on - R.string.filter_all_apps, // All apps label, but personal filter (for high power); - R.string.filter_all_apps, // All apps - R.string.filter_enabled_apps, // Enabled - R.string.filter_apps_disabled, // Disabled - R.string.filter_notif_blocked_apps, // Blocked Notifications - R.string.filter_notif_priority_apps, // Priority Notifications - R.string.filter_notif_no_peeking, // No peeking Notifications - R.string.filter_notif_sensitive_apps, // Sensitive Notifications - R.string.filter_personal_apps, // Personal - R.string.filter_work_apps, // Work - R.string.filter_with_domain_urls_apps, // Domain URLs - R.string.filter_all_apps, // Usage access screen, never displayed - R.string.filter_overlay_apps, // Apps with overlay permission - R.string.filter_write_settings_apps, // Apps that can write system settings + public static final int[] FILTER_LABELS = new int[]{ + R.string.high_power_filter_on, // High power whitelist, on + R.string.filter_all_apps, // All apps label, but personal filter (for high power); + R.string.filter_all_apps, // All apps + R.string.filter_enabled_apps, // Enabled + R.string.filter_apps_disabled, // Disabled + R.string.filter_notif_blocked_apps, // Blocked Notifications + R.string.filter_notif_priority_apps, // Priority Notifications + R.string.filter_notif_no_peeking, // No peeking Notifications + R.string.filter_notif_sensitive_apps, // Sensitive Notifications + R.string.filter_personal_apps, // Personal + R.string.filter_work_apps, // Work + R.string.filter_with_domain_urls_apps, // Domain URLs + R.string.filter_all_apps, // Usage access screen, never displayed + R.string.filter_overlay_apps, // Apps with overlay permission + R.string.filter_write_settings_apps, // Apps that can write system settings }; // This is the actual mapping to filters from FILTER_ constants above, the order must // be kept in sync. - public static final AppFilter[] FILTERS = new AppFilter[] { - new CompoundFilter(AppStatePowerBridge.FILTER_POWER_WHITELISTED, - ApplicationsState.FILTER_ALL_ENABLED), // High power whitelist, on - new CompoundFilter(ApplicationsState.FILTER_PERSONAL_WITHOUT_DISABLED_UNTIL_USED, - ApplicationsState.FILTER_ALL_ENABLED), // All apps label, but personal filter - ApplicationsState.FILTER_EVERYTHING, // All apps - ApplicationsState.FILTER_ALL_ENABLED, // Enabled - ApplicationsState.FILTER_DISABLED, // Disabled - AppStateNotificationBridge.FILTER_APP_NOTIFICATION_BLOCKED, // Blocked Notifications - AppStateNotificationBridge.FILTER_APP_NOTIFICATION_PRIORITY, // Priority Notifications - AppStateNotificationBridge.FILTER_APP_NOTIFICATION_NO_PEEK, // No peeking Notifications - AppStateNotificationBridge.FILTER_APP_NOTIFICATION_SENSITIVE, // Sensitive Notifications - ApplicationsState.FILTER_PERSONAL, // Personal - ApplicationsState.FILTER_WORK, // Work - ApplicationsState.FILTER_WITH_DOMAIN_URLS, // Apps with Domain URLs - AppStateUsageBridge.FILTER_APP_USAGE, // Apps with Domain URLs - AppStateOverlayBridge.FILTER_SYSTEM_ALERT_WINDOW, // Apps that can draw overlays - AppStateWriteSettingsBridge.FILTER_WRITE_SETTINGS, // Apps that can write system settings + public static final AppFilter[] FILTERS = new AppFilter[]{ + new CompoundFilter(AppStatePowerBridge.FILTER_POWER_WHITELISTED, + ApplicationsState.FILTER_ALL_ENABLED), // High power whitelist, on + new CompoundFilter(ApplicationsState.FILTER_PERSONAL_WITHOUT_DISABLED_UNTIL_USED, + ApplicationsState.FILTER_ALL_ENABLED), // All apps label, but personal filter + ApplicationsState.FILTER_EVERYTHING, // All apps + ApplicationsState.FILTER_ALL_ENABLED, // Enabled + ApplicationsState.FILTER_DISABLED, // Disabled + AppStateNotificationBridge.FILTER_APP_NOTIFICATION_BLOCKED, // Blocked Notifications + AppStateNotificationBridge.FILTER_APP_NOTIFICATION_PRIORITY, // Priority Notifications + AppStateNotificationBridge.FILTER_APP_NOTIFICATION_NO_PEEK, // No peeking Notifications + AppStateNotificationBridge.FILTER_APP_NOTIFICATION_SENSITIVE, // Sensitive Notifications + ApplicationsState.FILTER_PERSONAL, // Personal + ApplicationsState.FILTER_WORK, // Work + ApplicationsState.FILTER_WITH_DOMAIN_URLS, // Apps with Domain URLs + AppStateUsageBridge.FILTER_APP_USAGE, // Apps with Domain URLs + AppStateOverlayBridge.FILTER_SYSTEM_ALERT_WINDOW, // Apps that can draw overlays + AppStateWriteSettingsBridge.FILTER_WRITE_SETTINGS, // Apps that can write system settings }; // sort order @@ -201,13 +202,13 @@ public class ManageApplications extends InstrumentedFragment private Menu mOptionsMenu; - public static final int LIST_TYPE_MAIN = 0; + public static final int LIST_TYPE_MAIN = 0; public static final int LIST_TYPE_NOTIFICATION = 1; public static final int LIST_TYPE_DOMAINS_URLS = 2; - public static final int LIST_TYPE_STORAGE = 3; + public static final int LIST_TYPE_STORAGE = 3; public static final int LIST_TYPE_USAGE_ACCESS = 4; - public static final int LIST_TYPE_HIGH_POWER = 5; - public static final int LIST_TYPE_OVERLAY = 6; + public static final int LIST_TYPE_HIGH_POWER = 5; + public static final int LIST_TYPE_OVERLAY = 6; public static final int LIST_TYPE_WRITE_SETTINGS = 7; private View mRootView; @@ -280,7 +281,7 @@ public class ManageApplications extends InstrumentedFragment @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { + Bundle savedInstanceState) { // initialize the inflater mInflater = inflater; @@ -550,7 +551,7 @@ public class ManageApplications extends InstrumentedFragment @Override public boolean onOptionsItemSelected(MenuItem item) { int menuId = item.getItemId(); - switch(item.getItemId()) { + switch (item.getItemId()) { case R.id.sort_order_alpha: case R.id.sort_order_size: mSortOrder = menuId; @@ -713,7 +714,7 @@ public class ManageApplications extends InstrumentedFragment private ArrayList mBaseEntries; private ArrayList mEntries; private boolean mResumed; - private int mLastSortMode=-1; + private int mLastSortMode = -1; private int mWhichSize = SIZE_TOTAL; CharSequence mCurFilterPrefix; private PackageManager mPm; @@ -742,7 +743,7 @@ public class ManageApplications extends InstrumentedFragment }; public ApplicationsAdapter(ApplicationsState state, ManageApplications manageApplications, - int filterMode) { + int filterMode) { mState = state; mSession = state.newSession(this); mManageApplications = manageApplications; @@ -895,7 +896,7 @@ public class ManageApplications extends InstrumentedFragment } ArrayList applyPrefixFilter(CharSequence prefix, - ArrayList origEntries) { + ArrayList origEntries) { if (prefix == null || prefix.length() == 0) { return origEntries; } else { @@ -903,7 +904,7 @@ public class ManageApplications extends InstrumentedFragment final String spacePrefixStr = " " + prefixStr; ArrayList newEntries = new ArrayList(); - for (int i=0; i apps) { + if (apps == null) return; + mLoader.setSummary(this, mContext.getString(R.string.apps_summary, apps.size())); + } + + @Override + public void onRebuildComplete(ArrayList apps) { + updateSummary(apps); + } + + @Override + public void onPackageListChanged() { + updateSummary(mSession.rebuild(ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER, + ApplicationsState.ALPHA_COMPARATOR)); + } + + @Override + public void onLauncherInfoChanged() { + updateSummary(mSession.rebuild(ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER, + ApplicationsState.ALPHA_COMPARATOR)); + } + + @Override + public void onLoadEntriesCompleted() { + updateSummary(mSession.rebuild(ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER, + ApplicationsState.ALPHA_COMPARATOR)); + } + + @Override + public void onRunningStateChanged(boolean running) { + } + + @Override + public void onPackageIconChanged() { + } + + @Override + public void onPackageSizeChanged(String packageName) { + } + + @Override + public void onAllSizesComputed() { + } + } + + public static final SummaryLoader.SummaryProviderFactory SUMMARY_PROVIDER_FACTORY + = new SummaryLoader.SummaryProviderFactory() { + @Override + public SummaryLoader.SummaryProvider createSummaryProvider(Activity activity, + SummaryLoader summaryLoader) { + return new SummaryProvider(activity, summaryLoader); + } + }; } diff --git a/src/com/android/settings/bluetooth/BluetoothSettings.java b/src/com/android/settings/bluetooth/BluetoothSettings.java index 8a1ef469681..eac89b18d14 100644 --- a/src/com/android/settings/bluetooth/BluetoothSettings.java +++ b/src/com/android/settings/bluetooth/BluetoothSettings.java @@ -16,6 +16,7 @@ package com.android.settings.bluetooth; +import android.app.Activity; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.content.BroadcastReceiver; @@ -39,16 +40,17 @@ import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.widget.TextView; - import com.android.internal.logging.MetricsLogger; import com.android.settings.LinkifyUtils; import com.android.settings.R; import com.android.settings.SettingsActivity; +import com.android.settings.dashboard.SummaryLoader; import com.android.settings.location.ScanningSettings; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.search.Indexable; import com.android.settings.search.SearchIndexableRaw; import com.android.settings.widget.SwitchBar; +import com.android.settingslib.bluetooth.BluetoothCallback; import com.android.settingslib.bluetooth.BluetoothDeviceFilter; import com.android.settingslib.bluetooth.CachedBluetoothDevice; import com.android.settingslib.bluetooth.LocalBluetoothManager; @@ -477,6 +479,84 @@ public final class BluetoothSettings extends DeviceListPreferenceFragment implem return R.string.help_url_bluetooth; } + private static class SummaryProvider + implements SummaryLoader.SummaryProvider, BluetoothCallback { + + private final LocalBluetoothManager mBluetoothManager; + private final Context mContext; + private final SummaryLoader mSummaryLoader; + + private boolean mEnabled; + private boolean mConnected; + + public SummaryProvider(Context context, SummaryLoader summaryLoader) { + mBluetoothManager = Utils.getLocalBtManager(context); + mContext = context; + mSummaryLoader = summaryLoader; + } + + @Override + public void setListening(boolean listening) { + if (listening) { + BluetoothAdapter defaultAdapter = BluetoothAdapter.getDefaultAdapter(); + mEnabled = defaultAdapter.isEnabled(); + mConnected = + defaultAdapter.getConnectionState() == BluetoothAdapter.STATE_CONNECTED; + mSummaryLoader.setSummary(this, getSummary()); + mBluetoothManager.getEventManager().registerCallback(this); + } else { + mBluetoothManager.getEventManager().unregisterCallback(this); + } + } + + private CharSequence getSummary() { + return mContext.getString(!mEnabled ? R.string.disabled + : mConnected ? R.string.bluetooth_connected + : R.string.bluetooth_disconnected); + } + + @Override + public void onBluetoothStateChanged(int bluetoothState) { + mEnabled = bluetoothState == BluetoothAdapter.STATE_ON; + mSummaryLoader.setSummary(this, getSummary()); + } + + @Override + public void onConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) { + mConnected = state == BluetoothAdapter.STATE_CONNECTED; + mSummaryLoader.setSummary(this, getSummary()); + } + + @Override + public void onScanningStateChanged(boolean started) { + + } + + @Override + public void onDeviceAdded(CachedBluetoothDevice cachedDevice) { + + } + + @Override + public void onDeviceDeleted(CachedBluetoothDevice cachedDevice) { + + } + + @Override + public void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState) { + + } + } + + public static final SummaryLoader.SummaryProviderFactory SUMMARY_PROVIDER_FACTORY + = new SummaryLoader.SummaryProviderFactory() { + @Override + public SummaryLoader.SummaryProvider createSummaryProvider(Activity activity, + SummaryLoader summaryLoader) { + return new SummaryProvider(activity, summaryLoader); + } + }; + public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = new BaseSearchIndexProvider() { @Override diff --git a/src/com/android/settings/dashboard/DashboardAdapter.java b/src/com/android/settings/dashboard/DashboardAdapter.java new file mode 100644 index 00000000000..e2024f7a881 --- /dev/null +++ b/src/com/android/settings/dashboard/DashboardAdapter.java @@ -0,0 +1,200 @@ +/* + * Copyright (C) 2015 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.dashboard; + +import android.content.Context; +import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; +import android.util.Log; +import android.util.TypedValue; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; +import com.android.internal.util.ArrayUtils; +import com.android.settings.SettingsActivity; +import com.android.settingslib.drawer.DashboardCategory; +import com.android.settingslib.drawer.DashboardTile; + +import java.util.ArrayList; +import java.util.List; + +public class DashboardAdapter extends RecyclerView.Adapter { + public static final String TAG = "DashboardAdapter"; + + private final List mItems = new ArrayList<>(); + private final List mTypes = new ArrayList<>(); + private final List mIds = new ArrayList<>(); + + private final List mCategories; + private final Context mContext; + + private boolean mIsShowingAll; + // Used for counting items; + private int mId; + + public DashboardAdapter(Context context, List categories) { + mContext = context; + mCategories = categories; + + // TODO: Better place for tinting? + TypedValue tintColor = new TypedValue(); + context.getTheme().resolveAttribute(com.android.internal.R.attr.colorAccent, + tintColor, true); + for (int i = 0; i < categories.size(); i++) { + for (int j = 0; j < categories.get(i).tiles.size(); j++) { + DashboardTile tile = categories.get(i).tiles.get(j); + + if (!context.getPackageName().equals( + tile.intent.getComponent().getPackageName())) { + // If this drawable is coming from outside Settings, tint it to match the + // color. + tile.icon.setTint(tintColor.data); + } + } + } + + setShowingAll(false); + setHasStableIds(true); + } + + public void notifyChanged(DashboardTile tile) { + for (int i = 0; i < mItems.size(); i++) { + if (mItems.get(i) == tile) { + notifyItemChanged(i); + return; + } + } + } + + public void setShowingAll(boolean showingAll) { + mIsShowingAll = showingAll; + reset(); + countItem(null, com.android.settings.R.layout.dashboard_spacer, true); + for (int i = 0; i < mCategories.size(); i++) { + DashboardCategory category = mCategories.get(i); + countItem(category, com.android.settings.R.layout.dashboard_category, mIsShowingAll); + for (int j = 0; j < category.tiles.size(); j++) { + DashboardTile tile = category.tiles.get(j); + Log.d(TAG, "Maybe adding " + tile.intent.getComponent().getClassName()); + countItem(tile, com.android.settings.R.layout.dashboard_tile, mIsShowingAll + || ArrayUtils.contains(DashboardSummary.INITIAL_ITEMS, + tile.intent.getComponent().getClassName())); + } + } + countItem(null, com.android.settings.R.layout.see_all, true); + notifyDataSetChanged(); + } + + private void reset() { + mItems.clear(); + mTypes.clear(); + mIds.clear(); + mId = 0; + } + + private void countItem(Object object, int type, boolean add) { + if (add) { + mItems.add(object); + mTypes.add(type); + mIds.add(mId); + } + mId++; + } + + @Override + public DashboardItemHolder onCreateViewHolder(ViewGroup parent, int viewType) { + return new DashboardItemHolder(LayoutInflater.from(parent.getContext()).inflate( + viewType, parent, false)); + } + + @Override + public void onBindViewHolder(DashboardItemHolder holder, int position) { + switch (mTypes.get(position)) { + case com.android.settings.R.layout.dashboard_category: + onBindCategory(holder, (DashboardCategory) mItems.get(position)); + break; + case com.android.settings.R.layout.dashboard_tile: + final DashboardTile tile = (DashboardTile) mItems.get(position); + onBindTile(holder, tile); + holder.itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + ((SettingsActivity) mContext).openTile(tile); + } + }); + break; + case com.android.settings.R.layout.see_all: + onBindSeeAll(holder); + holder.itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + setShowingAll(!mIsShowingAll); + } + }); + break; + } + } + + private void onBindTile(DashboardItemHolder holder, DashboardTile dashboardTile) { + holder.icon.setImageIcon(dashboardTile.icon); + holder.title.setText(dashboardTile.title); + if (!TextUtils.isEmpty(dashboardTile.summary)) { + holder.summary.setText(dashboardTile.summary); + holder.summary.setVisibility(View.VISIBLE); + } else { + holder.summary.setVisibility(View.GONE); + } + } + + private void onBindCategory(DashboardItemHolder holder, DashboardCategory category) { + holder.title.setText(category.title); + } + + private void onBindSeeAll(DashboardItemHolder holder) { + holder.title.setText(mIsShowingAll ? com.android.settings.R.string.see_less + : com.android.settings.R.string.see_all); + } + + @Override + public long getItemId(int position) { + return mIds.get(position); + } + + @Override + public int getItemViewType(int position) { + return mTypes.get(position); + } + + @Override + public int getItemCount() { + return mIds.size(); + } + + public static class DashboardItemHolder extends RecyclerView.ViewHolder { + private final ImageView icon; + private final TextView title; + private final TextView summary; + + public DashboardItemHolder(View itemView) { + super(itemView); + icon = (ImageView) itemView.findViewById(android.R.id.icon); + title = (TextView) itemView.findViewById(android.R.id.title); + summary = (TextView) itemView.findViewById(android.R.id.summary); + } + } +} diff --git a/src/com/android/settings/dashboard/DashboardSummary.java b/src/com/android/settings/dashboard/DashboardSummary.java index c376d20ccaa..84464756a45 100644 --- a/src/com/android/settings/dashboard/DashboardSummary.java +++ b/src/com/android/settings/dashboard/DashboardSummary.java @@ -25,41 +25,33 @@ import android.os.Handler; import android.os.Message; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; -import android.text.TextUtils; import android.util.Log; -import android.util.TypedValue; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.TextView; import com.android.internal.logging.MetricsLogger; -import com.android.internal.util.ArrayUtils; import com.android.settings.HelpUtils; import com.android.settings.InstrumentedFragment; import com.android.settings.R; import com.android.settings.Settings; import com.android.settings.SettingsActivity; import com.android.settingslib.drawer.DashboardCategory; -import com.android.settingslib.drawer.DashboardTile; -import java.util.ArrayList; import java.util.List; public class DashboardSummary extends InstrumentedFragment { - private static final boolean DEBUG = true; + public static final boolean DEBUG = true; private static final String TAG = "DashboardSummary"; public static final String[] INITIAL_ITEMS = new String[] { Settings.WifiSettingsActivity.class.getName(), + Settings.BluetoothSettingsActivity.class.getName(), Settings.DataUsageSummaryActivity.class.getName(), Settings.PowerUsageSummaryActivity.class.getName(), Settings.ManageApplicationsActivity.class.getName(), Settings.StorageSettingsActivity.class.getName(), - Settings.DisplaySettingsActivity.class.getName(), - Settings.NotificationSettingsActivity.class.getName(), }; private static final int MSG_REBUILD_UI = 1; @@ -68,6 +60,7 @@ public class DashboardSummary extends InstrumentedFragment { private RecyclerView mDashboard; private DashboardAdapter mAdapter; + private SummaryLoader mSummaryLoader; @Override protected int getMetricsCategory() { @@ -78,6 +71,10 @@ public class DashboardSummary extends InstrumentedFragment { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + List categories = + ((SettingsActivity) getActivity()).getDashboardCategories(true); + mAdapter = new DashboardAdapter(getContext(), categories); + mSummaryLoader = new SummaryLoader(getActivity(), mAdapter, categories); setHasOptionsMenu(true); } @@ -101,6 +98,7 @@ public class DashboardSummary extends InstrumentedFragment { filter.addAction(Intent.ACTION_PACKAGE_REPLACED); filter.addDataScheme("package"); getActivity().registerReceiver(mHomePackageReceiver, filter); + mSummaryLoader.setListening(true); } @Override @@ -108,6 +106,7 @@ public class DashboardSummary extends InstrumentedFragment { super.onPause(); getActivity().unregisterReceiver(mHomePackageReceiver); + mSummaryLoader.setListening(false); } @Override @@ -134,8 +133,6 @@ public class DashboardSummary extends InstrumentedFragment { } long start = System.currentTimeMillis(); - mAdapter = new DashboardAdapter(getContext(), - ((SettingsActivity) getActivity()).getDashboardCategories(true)); mDashboard.setAdapter(mAdapter); long delta = System.currentTimeMillis() - start; @@ -167,158 +164,4 @@ public class DashboardSummary extends InstrumentedFragment { } } - private static class DashboardItemHolder extends RecyclerView.ViewHolder { - private final ImageView icon; - private final TextView title; - private final TextView summary; - - public DashboardItemHolder(View itemView) { - super(itemView); - icon = (ImageView) itemView.findViewById(android.R.id.icon); - title = (TextView) itemView.findViewById(android.R.id.title); - summary = (TextView) itemView.findViewById(android.R.id.summary); - } - } - - private static class DashboardAdapter extends RecyclerView.Adapter { - - private final List mItems = new ArrayList<>(); - private final List mTypes = new ArrayList<>(); - private final List mIds = new ArrayList<>(); - - private final List mCategories; - private final Context mContext; - - private boolean mIsShowingAll; - // Used for counting items; - private int mId; - - public DashboardAdapter(Context context, List categories) { - mContext = context; - mCategories = categories; - - // TODO: Better place for tinting? - TypedValue tintColor = new TypedValue(); - context.getTheme().resolveAttribute(com.android.internal.R.attr.colorAccent, - tintColor, true); - for (int i = 0; i < categories.size(); i++) { - for (int j = 0; j < categories.get(i).tiles.size(); j++) { - DashboardTile tile = categories.get(i).tiles.get(j); - - if (!context.getPackageName().equals( - tile.intent.getComponent().getPackageName())) { - // If this drawable is coming from outside Settings, tint it to match the - // color. - tile.icon.setTint(tintColor.data); - } - } - } - - setShowingAll(false); - setHasStableIds(true); - } - - public void setShowingAll(boolean showingAll) { - mIsShowingAll = showingAll; - reset(); - countItem(null, R.layout.dashboard_spacer, true); - for (int i = 0; i < mCategories.size(); i++) { - DashboardCategory category = mCategories.get(i); - countItem(category, R.layout.dashboard_category, mIsShowingAll); - for (int j = 0; j < category.tiles.size(); j++) { - DashboardTile tile = category.tiles.get(j); - Log.d(TAG, "Maybe adding " + tile.intent.getComponent().getClassName()); - countItem(tile, R.layout.dashboard_tile, mIsShowingAll - || ArrayUtils.contains(INITIAL_ITEMS, - tile.intent.getComponent().getClassName())); - } - } - countItem(null, R.layout.see_all, true); - notifyDataSetChanged(); - } - - private void reset() { - mItems.clear(); - mTypes.clear(); - mIds.clear(); - mId = 0; - } - - private void countItem(Object object, int type, boolean add) { - if (add) { - mItems.add(object); - mTypes.add(type); - mIds.add(mId); - } - mId++; - } - - @Override - public DashboardItemHolder onCreateViewHolder(ViewGroup parent, int viewType) { - return new DashboardItemHolder(LayoutInflater.from(parent.getContext()).inflate( - viewType, parent, false)); - } - - @Override - public void onBindViewHolder(DashboardItemHolder holder, int position) { - switch (mTypes.get(position)) { - case R.layout.dashboard_category: - onBindCategory(holder, (DashboardCategory) mItems.get(position)); - break; - case R.layout.dashboard_tile: - final DashboardTile tile = (DashboardTile) mItems.get(position); - onBindTile(holder, tile); - holder.itemView.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - ((SettingsActivity) mContext).openTile(tile); - } - }); - break; - case R.layout.see_all: - onBindSeeAll(holder); - holder.itemView.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - setShowingAll(!mIsShowingAll); - } - }); - break; - } - } - - private void onBindTile(DashboardItemHolder holder, DashboardTile dashboardTile) { - holder.icon.setImageIcon(dashboardTile.icon); - holder.title.setText(dashboardTile.title); - if (!TextUtils.isEmpty(dashboardTile.summary)) { - holder.summary.setText(dashboardTile.summary); - holder.summary.setVisibility(View.VISIBLE); - } else { - holder.summary.setVisibility(View.GONE); - } - } - - private void onBindCategory(DashboardItemHolder holder, DashboardCategory category) { - holder.title.setText(category.title); - } - - private void onBindSeeAll(DashboardItemHolder holder) { - holder.title.setText(mIsShowingAll ? R.string.see_less : R.string.see_all); - } - - @Override - public long getItemId(int position) { - return mIds.get(position); - } - - @Override - public int getItemViewType(int position) { - return mTypes.get(position); - } - - @Override - public int getItemCount() { - return mIds.size(); - } - } } diff --git a/src/com/android/settings/dashboard/SummaryLoader.java b/src/com/android/settings/dashboard/SummaryLoader.java new file mode 100644 index 00000000000..4bbee8ccba2 --- /dev/null +++ b/src/com/android/settings/dashboard/SummaryLoader.java @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2015 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.dashboard; + +import android.app.Activity; +import android.content.pm.ActivityInfo; +import android.content.pm.PackageManager; +import android.os.Bundle; +import android.util.ArrayMap; +import android.util.Log; +import com.android.settings.SettingsActivity; +import com.android.settingslib.drawer.DashboardCategory; +import com.android.settingslib.drawer.DashboardTile; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; + +public class SummaryLoader { + private static final boolean DEBUG = DashboardSummary.DEBUG; + private static final String TAG = "SummaryLoader"; + + private final Activity mActivity; + private final DashboardAdapter mAdapter; + private final ArrayMap mSummaryMap = new ArrayMap<>(); + private final List mTiles = new ArrayList<>(); + + public static final String SUMMARY_PROVIDER_FACTORY = "SUMMARY_PROVIDER_FACTORY"; + + public SummaryLoader(Activity activity, DashboardAdapter adapter, + List categories) { + mActivity = activity; + mAdapter = adapter; + for (int i = 0; i < categories.size(); i++) { + List tiles = categories.get(i).tiles; + for (int j = 0; j < tiles.size(); j++) { + DashboardTile tile = tiles.get(j); + SummaryProvider provider = getSummaryProvider(tile); + if (provider != null) { + mSummaryMap.put(provider, tile); + } + } + } + } + + public void setSummary(SummaryProvider provider, CharSequence summary) { + DashboardTile tile = mSummaryMap.get(provider); + tile.summary = summary; + mAdapter.notifyChanged(tile); + } + + public void setListening(boolean listening) { + for (SummaryProvider provider : mSummaryMap.keySet()) { + provider.setListening(listening); + } + } + + private SummaryProvider getSummaryProvider(DashboardTile tile) { + if (!mActivity.getPackageName().equals(tile.intent.getComponent().getPackageName())) { + // Not within Settings, can't load Summary directly. + // TODO: Load summary indirectly. + return null; + } + Bundle metaData = getMetaData(tile); + if (metaData == null) { + if (DEBUG) Log.d(TAG, "No metadata specified for " + tile.intent.getComponent()); + return null; + } + String clsName = metaData.getString(SettingsActivity.META_DATA_KEY_FRAGMENT_CLASS); + if (clsName == null) { + if (DEBUG) Log.d(TAG, "No fragment specified for " + tile.intent.getComponent()); + return null; + } + try { + Class cls = Class.forName(clsName); + Field field = cls.getField(SUMMARY_PROVIDER_FACTORY); + SummaryProviderFactory factory = (SummaryProviderFactory) field.get(null); + return factory.createSummaryProvider(mActivity, this); + } catch (ClassNotFoundException e) { + if (DEBUG) Log.d(TAG, "Couldn't find " + clsName, e); + } catch (NoSuchFieldException e) { + if (DEBUG) Log.d(TAG, "Couldn't find " + SUMMARY_PROVIDER_FACTORY, e); + } catch (ClassCastException e) { + if (DEBUG) Log.d(TAG, "Couldn't cast " + SUMMARY_PROVIDER_FACTORY, e); + } catch (IllegalAccessException e) { + if (DEBUG) Log.d(TAG, "Couldn't get " + SUMMARY_PROVIDER_FACTORY, e); + } + return null; + } + + private Bundle getMetaData(DashboardTile tile) { + // TODO: Cache this in TileUtils so this doesn't need to be loaded again. + try { + ActivityInfo activityInfo = mActivity.getPackageManager().getActivityInfo( + tile.intent.getComponent(), PackageManager.GET_META_DATA); + return activityInfo.metaData; + } catch (PackageManager.NameNotFoundException e) { + return null; + } + } + + public interface SummaryProvider { + void setListening(boolean listening); + } + + public interface SummaryProviderFactory { + SummaryProvider createSummaryProvider(Activity activity, SummaryLoader summaryLoader); + } +} diff --git a/src/com/android/settings/deviceinfo/StorageSettings.java b/src/com/android/settings/deviceinfo/StorageSettings.java index 99e537f30a0..6b429862cff 100644 --- a/src/com/android/settings/deviceinfo/StorageSettings.java +++ b/src/com/android/settings/deviceinfo/StorageSettings.java @@ -16,6 +16,7 @@ package com.android.settings.deviceinfo; +import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.app.DialogFragment; @@ -39,10 +40,10 @@ import android.text.format.Formatter; import android.text.format.Formatter.BytesResult; import android.util.Log; import android.widget.Toast; - import com.android.internal.logging.MetricsLogger; import com.android.settings.R; import com.android.settings.SettingsPreferenceFragment; +import com.android.settings.dashboard.SummaryLoader; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.search.Indexable; import com.android.settings.search.SearchIndexableRaw; @@ -433,6 +434,52 @@ public class StorageSettings extends SettingsPreferenceFragment implements Index } } + private static class SummaryProvider implements SummaryLoader.SummaryProvider { + private final Context mContext; + private final SummaryLoader mLoader; + + private SummaryProvider(Context context, SummaryLoader loader) { + mContext = context; + mLoader = loader; + } + + @Override + public void setListening(boolean listening) { + if (listening) { + updateSummary(); + } + } + + private void updateSummary() { + // TODO: Register listener. + StorageManager storageManager = mContext.getSystemService(StorageManager.class); + final List volumes = storageManager.getVolumes(); + long privateUsedBytes = 0; + long privateTotalBytes = 0; + for (VolumeInfo info : volumes) { + if (info.getType() != VolumeInfo.TYPE_PUBLIC + && info.getType() != VolumeInfo.TYPE_PRIVATE) { + continue; + } + final File path = info.getPath(); + privateUsedBytes += path.getTotalSpace() - path.getFreeSpace(); + privateTotalBytes += path.getTotalSpace(); + } + mLoader.setSummary(this, mContext.getString(R.string.storage_summary, + Formatter.formatFileSize(mContext, privateUsedBytes), + Formatter.formatFileSize(mContext, privateTotalBytes))); + } + } + + public static final SummaryLoader.SummaryProviderFactory SUMMARY_PROVIDER_FACTORY + = new SummaryLoader.SummaryProviderFactory() { + @Override + public SummaryLoader.SummaryProvider createSummaryProvider(Activity activity, + SummaryLoader summaryLoader) { + return new SummaryProvider(activity, summaryLoader); + } + }; + /** * Enable indexing of searchable data */ diff --git a/src/com/android/settings/fuelgauge/BatteryHistoryChart.java b/src/com/android/settings/fuelgauge/BatteryHistoryChart.java index cd6c62f9a52..6c4d45774fd 100644 --- a/src/com/android/settings/fuelgauge/BatteryHistoryChart.java +++ b/src/com/android/settings/fuelgauge/BatteryHistoryChart.java @@ -155,15 +155,13 @@ public class BatteryHistoryChart extends View { final Path mWifiRunningPath = new Path(); final Path mCpuRunningPath = new Path(); final Path mDateLinePath = new Path(); - + BatteryStats mStats; Intent mBatteryBroadcast; long mStatsPeriod; - int mBatteryLevel; String mMaxPercentLabelString; String mMinPercentLabelString; String mDurationString; - String mChargeLabelString; String mChargeDurationString; String mDrainString; String mChargingLabel; @@ -175,6 +173,8 @@ public class BatteryHistoryChart extends View { String mCpuRunningLabel; String mPhoneSignalLabel; + BatteryInfo mInfo; + int mChartMinHeight; int mHeaderHeight; @@ -220,7 +220,6 @@ public class BatteryHistoryChart extends View { long mStartWallTime; long mEndDataWallTime; long mEndWallTime; - boolean mDischarging; int mBatLow; int mBatHigh; boolean mHaveWifi; @@ -510,54 +509,10 @@ public class BatteryHistoryChart extends View { mMaxPercentLabelString = Utils.formatPercentage(100); mMinPercentLabelString = Utils.formatPercentage(0); - - mBatteryLevel = com.android.settings.Utils.getBatteryLevel(mBatteryBroadcast); - String batteryPercentString = Utils.formatPercentage(mBatteryLevel); - long remainingTimeUs = 0; - mDischarging = true; - if (mBatteryBroadcast.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) == 0) { - final long drainTime = mStats.computeBatteryTimeRemaining(elapsedRealtimeUs); - if (drainTime > 0) { - remainingTimeUs = drainTime; - String timeString = Formatter.formatShortElapsedTime(getContext(), - drainTime / 1000); - mChargeLabelString = getContext().getResources().getString( - R.string.power_discharging_duration, batteryPercentString, timeString); - } else { - mChargeLabelString = batteryPercentString; - } - } else { - final long chargeTime = mStats.computeChargeTimeRemaining(elapsedRealtimeUs); - final String statusLabel = com.android.settings.Utils.getBatteryStatus(getResources(), - mBatteryBroadcast); - final int status = mBatteryBroadcast.getIntExtra(BatteryManager.EXTRA_STATUS, - BatteryManager.BATTERY_STATUS_UNKNOWN); - if (chargeTime > 0 && status != BatteryManager.BATTERY_STATUS_FULL) { - mDischarging = false; - remainingTimeUs = chargeTime; - String timeString = Formatter.formatShortElapsedTime(getContext(), - chargeTime / 1000); - int plugType = mBatteryBroadcast.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0); - int resId; - if (plugType == BatteryManager.BATTERY_PLUGGED_AC) { - resId = R.string.power_charging_duration_ac; - } else if (plugType == BatteryManager.BATTERY_PLUGGED_USB) { - resId = R.string.power_charging_duration_usb; - } else if (plugType == BatteryManager.BATTERY_PLUGGED_WIRELESS) { - resId = R.string.power_charging_duration_wireless; - } else { - resId = R.string.power_charging_duration; - } - mChargeLabelString = getContext().getResources().getString( - resId, batteryPercentString, timeString); - } else { - mChargeLabelString = getContext().getResources().getString( - R.string.power_charging, batteryPercentString, statusLabel); - } - } + mInfo = getBatteryInfo(getContext(), mBatteryBroadcast, mStats, elapsedRealtimeUs); mDrainString = ""; mChargeDurationString = ""; - setContentDescription(mChargeLabelString); + setContentDescription(mInfo.mChargeLabelString); int pos = 0; int lastInteresting = 0; @@ -613,9 +568,9 @@ public class BatteryHistoryChart extends View { } } } - mHistEnd = mHistDataEnd + (remainingTimeUs/1000); + mHistEnd = mHistDataEnd + (mInfo.remainingTimeUs/1000); mEndDataWallTime = lastWallTime + mHistDataEnd - lastRealtime; - mEndWallTime = mEndDataWallTime + (remainingTimeUs/1000); + mEndWallTime = mEndDataWallTime + (mInfo.remainingTimeUs/1000); mNumHist = lastInteresting; mHaveGps = (aggrStates&HistoryItem.STATE_GPS_ON_FLAG) != 0; mHaveFlashlight = (aggrStates2&HistoryItem.STATE2_FLASHLIGHT_FLAG) != 0; @@ -635,7 +590,7 @@ public class BatteryHistoryChart extends View { mMaxPercentLabelStringWidth = (int)mTextPaint.measureText(mMaxPercentLabelString); mMinPercentLabelStringWidth = (int)mTextPaint.measureText(mMinPercentLabelString); mDrainStringWidth = (int)mHeaderTextPaint.measureText(mDrainString); - mChargeLabelStringWidth = (int)mHeaderTextPaint.measureText(mChargeLabelString); + mChargeLabelStringWidth = (int)mHeaderTextPaint.measureText(mInfo.mChargeLabelString); mChargeDurationStringWidth = (int)mHeaderTextPaint.measureText(mChargeDurationString); mTextAscent = (int)mTextPaint.ascent(); mTextDescent = (int)mTextPaint.descent(); @@ -1029,9 +984,9 @@ public class BatteryHistoryChart extends View { if (lastY < 0 || lastX < 0) { // Didn't get any data... x = lastX = mLevelLeft; - y = lastY = mLevelTop + levelh - ((mBatteryLevel-batLow)*(levelh-1))/batChange; + y = lastY = mLevelTop + levelh - ((mInfo.mBatteryLevel-batLow)*(levelh-1))/batChange; Path path; - byte value = (byte)mBatteryLevel; + byte value = (byte)mInfo.mBatteryLevel; if (value <= mBatteryCriticalLevel) path = mBatCriticalPath; else if (value <= mBatteryWarnLevel) path = mBatWarnPath; else path = null; //mBatGoodPath; @@ -1060,7 +1015,7 @@ public class BatteryHistoryChart extends View { mTimeRemainPath.moveTo(x, lastY); int fullY = mLevelTop + levelh - ((100-batLow)*(levelh-1))/batChange; int emptyY = mLevelTop + levelh - ((0-batLow)*(levelh-1))/batChange; - if (mDischarging) { + if (mInfo.mDischarging) { mTimeRemainPath.lineTo(mLevelRight, emptyY); } else { mTimeRemainPath.lineTo(mLevelRight, fullY); @@ -1257,8 +1212,8 @@ public class BatteryHistoryChart extends View { int headerTop = -mHeaderTextAscent + (mHeaderTextDescent-mHeaderTextAscent)/3; mHeaderTextPaint.setTextAlign(textAlignLeft); - if (DEBUG) Log.d(TAG, "Drawing charge label string: " + mChargeLabelString); - canvas.drawText(mChargeLabelString, textStartX, headerTop, mHeaderTextPaint); + if (DEBUG) Log.d(TAG, "Drawing charge label string: " + mInfo.mChargeLabelString); + canvas.drawText(mInfo.mChargeLabelString, textStartX, headerTop, mHeaderTextPaint); int stringHalfWidth = mChargeDurationStringWidth / 2; if (layoutRtl) stringHalfWidth = -stringHalfWidth; int headerCenter = ((width-mChargeDurationStringWidth-mDrainStringWidth)/2) @@ -1404,4 +1359,59 @@ public class BatteryHistoryChart extends View { } } } + + public static class BatteryInfo { + public String mChargeLabelString; + public int mBatteryLevel; + public boolean mDischarging = true; + public long remainingTimeUs = 0; + } + + public static BatteryInfo getBatteryInfo(Context context, Intent batteryBroadcast, + BatteryStats stats, long elapsedRealtimeUs) { + BatteryInfo info = new BatteryInfo(); + info.mBatteryLevel = com.android.settings.Utils.getBatteryLevel(batteryBroadcast); + String batteryPercentString = Utils.formatPercentage(info.mBatteryLevel); + if (batteryBroadcast.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) == 0) { + final long drainTime = stats.computeBatteryTimeRemaining(elapsedRealtimeUs); + if (drainTime > 0) { + info.remainingTimeUs = drainTime; + String timeString = Formatter.formatShortElapsedTime(context, + drainTime / 1000); + info.mChargeLabelString = context.getResources().getString( + R.string.power_discharging_duration, batteryPercentString, timeString); + } else { + info.mChargeLabelString = batteryPercentString; + } + } else { + final long chargeTime = stats.computeChargeTimeRemaining(elapsedRealtimeUs); + final String statusLabel = com.android.settings.Utils.getBatteryStatus( + context.getResources(), batteryBroadcast); + final int status = batteryBroadcast.getIntExtra(BatteryManager.EXTRA_STATUS, + BatteryManager.BATTERY_STATUS_UNKNOWN); + if (chargeTime > 0 && status != BatteryManager.BATTERY_STATUS_FULL) { + info.mDischarging = false; + info.remainingTimeUs = chargeTime; + String timeString = Formatter.formatShortElapsedTime(context, + chargeTime / 1000); + int plugType = batteryBroadcast.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0); + int resId; + if (plugType == BatteryManager.BATTERY_PLUGGED_AC) { + resId = R.string.power_charging_duration_ac; + } else if (plugType == BatteryManager.BATTERY_PLUGGED_USB) { + resId = R.string.power_charging_duration_usb; + } else if (plugType == BatteryManager.BATTERY_PLUGGED_WIRELESS) { + resId = R.string.power_charging_duration_wireless; + } else { + resId = R.string.power_charging_duration; + } + info.mChargeLabelString = context.getResources().getString( + resId, batteryPercentString, timeString); + } else { + info.mChargeLabelString = context.getResources().getString( + R.string.power_charging, batteryPercentString, statusLabel); + } + } + return info; + } } diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java index 255270d656d..25c0fc29cb7 100644 --- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java +++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java @@ -17,13 +17,18 @@ package com.android.settings.fuelgauge; import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; import android.graphics.drawable.Drawable; +import android.os.AsyncTask; import android.os.BatteryStats; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.os.Process; +import android.os.SystemClock; import android.os.UserHandle; import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceGroup; @@ -32,15 +37,16 @@ import android.util.TypedValue; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; - import com.android.internal.logging.MetricsLogger; import com.android.internal.os.BatterySipper; import com.android.internal.os.BatterySipper.DrainType; +import com.android.internal.os.BatteryStatsHelper; import com.android.internal.os.PowerProfile; import com.android.settings.R; import com.android.settings.Settings.HighPowerApplicationsActivity; import com.android.settings.SettingsActivity; import com.android.settings.applications.ManageApplications; +import com.android.settings.dashboard.SummaryLoader; import java.util.ArrayList; import java.util.Collections; @@ -431,4 +437,49 @@ public class PowerUsageSummary extends PowerUsageBase { super.handleMessage(msg); } }; + + private static class SummaryProvider implements SummaryLoader.SummaryProvider { + private final Context mContext; + private final SummaryLoader mLoader; + + private SummaryProvider(Context context, SummaryLoader loader) { + mContext = context; + mLoader = loader; + } + + @Override + public void setListening(boolean listening) { + if (listening) { + // TODO: Listen. + new AsyncTask() { + @Override + protected BatteryStats doInBackground(Void... params) { + BatteryStatsHelper statsHelper = new BatteryStatsHelper(mContext, true); + statsHelper.create((Bundle) null); + return statsHelper.getStats(); + } + + @Override + protected void onPostExecute(BatteryStats batteryStats) { + final long elapsedRealtimeUs = SystemClock.elapsedRealtime() * 1000; + Intent batteryBroadcast = mContext.registerReceiver(null, + new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); + BatteryHistoryChart.BatteryInfo batteryInfo = BatteryHistoryChart + .getBatteryInfo(mContext, batteryBroadcast, batteryStats, + elapsedRealtimeUs); + mLoader.setSummary(SummaryProvider.this, batteryInfo.mChargeLabelString); + } + }.execute(); + } + } + } + + public static final SummaryLoader.SummaryProviderFactory SUMMARY_PROVIDER_FACTORY + = new SummaryLoader.SummaryProviderFactory() { + @Override + public SummaryLoader.SummaryProvider createSummaryProvider(Activity activity, + SummaryLoader summaryLoader) { + return new SummaryProvider(activity, summaryLoader); + } + }; } diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java index c9a94b72748..00b311c2117 100644 --- a/src/com/android/settings/wifi/WifiSettings.java +++ b/src/com/android/settings/wifi/WifiSettings.java @@ -21,9 +21,11 @@ import android.app.AlertDialog; import android.app.AppGlobals; import android.app.Dialog; import android.app.admin.DevicePolicyManager; +import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; @@ -58,12 +60,12 @@ import android.widget.ProgressBar; import android.widget.TextView; import android.widget.TextView.BufferType; import android.widget.Toast; - import com.android.internal.logging.MetricsLogger; import com.android.settings.LinkifyUtils; import com.android.settings.R; import com.android.settings.RestrictedSettingsFragment; import com.android.settings.SettingsActivity; +import com.android.settings.dashboard.SummaryLoader; import com.android.settings.location.ScanningSettings; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.search.Indexable; @@ -71,6 +73,7 @@ import com.android.settings.search.SearchIndexableRaw; import com.android.settings.wifi.AccessPointPreference.UserBadgeCache; import com.android.settingslib.wifi.AccessPoint; import com.android.settingslib.wifi.AccessPoint.AccessPointListener; +import com.android.settingslib.wifi.WifiStatusTracker; import com.android.settingslib.wifi.WifiTracker; import java.util.ArrayList; @@ -1002,4 +1005,58 @@ public class WifiSettings extends RestrictedSettingsFragment Settings.Global.WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN, 0) != 0; return !isLockdownFeatureEnabled; } + + private static class SummaryProvider extends BroadcastReceiver + implements SummaryLoader.SummaryProvider { + + private final Context mContext; + private final WifiManager mWifiManager; + private final WifiStatusTracker mWifiTracker; + private final SummaryLoader mSummaryLoader; + + public SummaryProvider(Context context, SummaryLoader summaryLoader) { + mContext = context; + mSummaryLoader = summaryLoader; + mWifiManager = context.getSystemService(WifiManager.class); + mWifiTracker = new WifiStatusTracker(mWifiManager); + } + + private CharSequence getSummary() { + if (!mWifiTracker.enabled) { + return mContext.getString(R.string.disabled); + } + if (!mWifiTracker.connected) { + return mContext.getString(R.string.disconnected); + } + return mWifiTracker.ssid; + } + + @Override + public void setListening(boolean listening) { + if (listening) { + IntentFilter filter = new IntentFilter(); + filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); + filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); + filter.addAction(WifiManager.RSSI_CHANGED_ACTION); + mContext.registerReceiver(this, filter); + } else { + mContext.unregisterReceiver(this); + } + } + + @Override + public void onReceive(Context context, Intent intent) { + mWifiTracker.handleBroadcast(intent); + mSummaryLoader.setSummary(this, getSummary()); + } + } + + public static final SummaryLoader.SummaryProviderFactory SUMMARY_PROVIDER_FACTORY + = new SummaryLoader.SummaryProviderFactory() { + @Override + public SummaryLoader.SummaryProvider createSummaryProvider(Activity activity, + SummaryLoader summaryLoader) { + return new SummaryProvider(activity, summaryLoader); + } + }; }