diff options
| author | 2020-11-17 02:21:48 +0000 | |
|---|---|---|
| committer | 2020-11-17 02:21:48 +0000 | |
| commit | 92c2f231ed81346d13e96be8f98b2b49a3810ced (patch) | |
| tree | b398bc3810a4dddbf4aceb8fc6d82407f4700071 | |
| parent | a3bac99dc42f10944c47411de9867218dbec6618 (diff) | |
| parent | 7e30bd7222dab1635931c5368402cca272088c12 (diff) | |
Merge "Add non-app power consumers to the PowerStatsViewer"
12 files changed, 653 insertions, 455 deletions
diff --git a/core/tests/powertests/PowerStatsViewer/AndroidManifest.xml b/core/tests/powertests/PowerStatsViewer/AndroidManifest.xml index 378d0350e347..28ea05fca61e 100644 --- a/core/tests/powertests/PowerStatsViewer/AndroidManifest.xml +++ b/core/tests/powertests/PowerStatsViewer/AndroidManifest.xml @@ -35,8 +35,7 @@ </intent-filter> </activity> - <activity android:name=".AppPickerActivity" - android:label="Power Stats - Select an App"/> - + <activity android:name=".PowerConsumerPickerActivity" + android:label="Select a power consumer"/> </application> </manifest> diff --git a/core/tests/powertests/PowerStatsViewer/res/layout/app_info_layout.xml b/core/tests/powertests/PowerStatsViewer/res/layout/power_consumer_info_layout.xml index fe6fe2d41155..fbd0ebd61bc7 100644 --- a/core/tests/powertests/PowerStatsViewer/res/layout/app_info_layout.xml +++ b/core/tests/powertests/PowerStatsViewer/res/layout/power_consumer_info_layout.xml @@ -52,7 +52,7 @@ android:textAppearance="?android:attr/textAppearanceListItem"/> <TextView - android:id="@+id/uid" + android:id="@+id/details" android:layout_width="wrap_content" android:layout_height="wrap_content" android:ellipsize="marquee" diff --git a/core/tests/powertests/PowerStatsViewer/res/layout/power_consumer_picker_activity_layout.xml b/core/tests/powertests/PowerStatsViewer/res/layout/power_consumer_picker_activity_layout.xml new file mode 100644 index 000000000000..ecc89f0cb33e --- /dev/null +++ b/core/tests/powertests/PowerStatsViewer/res/layout/power_consumer_picker_activity_layout.xml @@ -0,0 +1,33 @@ +<!-- + ~ Copyright (C) 2020 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. + --> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> + + <com.google.android.material.tabs.TabLayout + android:id="@+id/tab_layout" + android:layout_width="match_parent" + android:layout_height="wrap_content"/> + + <androidx.viewpager.widget.ViewPager + android:id="@+id/pager" + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_weight="1" /> + +</LinearLayout> diff --git a/core/tests/powertests/PowerStatsViewer/res/layout/app_picker_layout.xml b/core/tests/powertests/PowerStatsViewer/res/layout/power_consumer_picker_layout.xml index 6f289996f982..bea38c18c20b 100644 --- a/core/tests/powertests/PowerStatsViewer/res/layout/app_picker_layout.xml +++ b/core/tests/powertests/PowerStatsViewer/res/layout/power_consumer_picker_layout.xml @@ -20,7 +20,7 @@ android:layout_height="match_parent"> <androidx.recyclerview.widget.RecyclerView - android:id="@+id/app_list_view" + android:id="@+id/list_view" android:layout_width="match_parent" android:layout_height="match_parent" android:visibility="gone"/> diff --git a/core/tests/powertests/PowerStatsViewer/res/layout/power_stats_viewer_layout.xml b/core/tests/powertests/PowerStatsViewer/res/layout/power_stats_viewer_layout.xml index 99494188f422..238e238deeaa 100644 --- a/core/tests/powertests/PowerStatsViewer/res/layout/power_stats_viewer_layout.xml +++ b/core/tests/powertests/PowerStatsViewer/res/layout/power_stats_viewer_layout.xml @@ -42,7 +42,7 @@ android:paddingStart="10dp" android:paddingEnd="10dp"> - <include layout="@layout/app_info_layout"/> + <include layout="@layout/power_consumer_info_layout"/> </LinearLayout> </androidx.cardview.widget.CardView> diff --git a/core/tests/powertests/PowerStatsViewer/src/com/android/frameworks/core/powerstatsviewer/AppInfoHelper.java b/core/tests/powertests/PowerStatsViewer/src/com/android/frameworks/core/powerstatsviewer/AppInfoHelper.java deleted file mode 100644 index 85265613928f..000000000000 --- a/core/tests/powertests/PowerStatsViewer/src/com/android/frameworks/core/powerstatsviewer/AppInfoHelper.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (C) 2020 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.frameworks.core.powerstatsviewer; - -import android.annotation.Nullable; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; -import android.os.Process; - -import com.android.internal.os.BatterySipper; - -class AppInfoHelper { - - private static final String SYSTEM_SERVER_PACKAGE_NAME = "android"; - - public static class AppInfo { - public int uid; - public CharSequence label; - public double powerMah; - public ApplicationInfo iconInfo; - public CharSequence packages; - } - - @Nullable - public static AppInfo makeApplicationInfo(PackageManager packageManager, int uid, - @Nullable BatterySipper sipper) { - if (sipper != null && sipper.drainType != BatterySipper.DrainType.APP) { - return null; - } - - String packageWithHighestDrain = null; - - AppInfo info = new AppInfo(); - info.uid = uid; - if (sipper != null) { - sipper.sumPower(); - info.powerMah = sipper.totalSmearedPowerMah; - packageWithHighestDrain = sipper.packageWithHighestDrain; - } - if (info.uid == Process.ROOT_UID) { - info.label = "<root>"; - } else { - String[] packages = packageManager.getPackagesForUid(info.uid); - String primaryPackageName = null; - if (info.uid == Process.SYSTEM_UID) { - primaryPackageName = SYSTEM_SERVER_PACKAGE_NAME; - } else if (packages != null) { - for (String name : packages) { - primaryPackageName = name; - if (name.equals(packageWithHighestDrain)) { - break; - } - } - } - - if (primaryPackageName != null) { - try { - ApplicationInfo applicationInfo = - packageManager.getApplicationInfo(primaryPackageName, 0); - info.label = applicationInfo.loadLabel(packageManager); - info.iconInfo = applicationInfo; - } catch (PackageManager.NameNotFoundException e) { - info.label = primaryPackageName; - } - } else if (packageWithHighestDrain != null) { - info.label = packageWithHighestDrain; - } - - if (packages != null && packages.length > 0) { - StringBuilder sb = new StringBuilder(); - if (primaryPackageName != null) { - sb.append(primaryPackageName); - } - for (String packageName : packages) { - if (packageName.equals(primaryPackageName)) { - continue; - } - - if (sb.length() != 0) { - sb.append(", "); - } - sb.append(packageName); - } - - info.packages = sb; - } - } - - // Default the app icon to System Server. This includes root, dex2oat and other UIDs. - if (info.iconInfo == null) { - try { - info.iconInfo = - packageManager.getApplicationInfo(SYSTEM_SERVER_PACKAGE_NAME, 0); - } catch (PackageManager.NameNotFoundException nameNotFoundException) { - // Won't happen - } - } - return info; - } -} diff --git a/core/tests/powertests/PowerStatsViewer/src/com/android/frameworks/core/powerstatsviewer/AppPickerActivity.java b/core/tests/powertests/PowerStatsViewer/src/com/android/frameworks/core/powerstatsviewer/AppPickerActivity.java deleted file mode 100644 index b4fc73c0f744..000000000000 --- a/core/tests/powertests/PowerStatsViewer/src/com/android/frameworks/core/powerstatsviewer/AppPickerActivity.java +++ /dev/null @@ -1,251 +0,0 @@ -/* - * Copyright (C) 2008 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.frameworks.core.powerstatsviewer; - -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.os.BatteryStats; -import android.os.Bundle; -import android.os.Process; -import android.os.UserManager; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.TextView; - -import androidx.activity.ComponentActivity; -import androidx.activity.result.contract.ActivityResultContract; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.loader.app.LoaderManager; -import androidx.loader.content.Loader; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; - -import com.android.frameworks.core.powerstatsviewer.AppInfoHelper.AppInfo; -import com.android.internal.os.BatterySipper; -import com.android.internal.os.BatteryStatsHelper; -import com.android.settingslib.utils.AsyncLoaderCompat; - -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; -import java.util.Locale; - -/** - * Picker, showing a sorted list of applications consuming power. Returns the selected - * application UID or Process.INVALID_UID. - */ -public class AppPickerActivity extends ComponentActivity { - private static final String TAG = "AppPicker"; - - public static final ActivityResultContract<Void, Integer> CONTRACT = - new ActivityResultContract<Void, Integer>() { - @NonNull - @Override - public Intent createIntent(@NonNull Context context, Void aVoid) { - return new Intent(context, AppPickerActivity.class); - } - - @Override - public Integer parseResult(int resultCode, @Nullable Intent intent) { - if (resultCode != RESULT_OK || intent == null) { - return Process.INVALID_UID; - } - return intent.getIntExtra(Intent.EXTRA_UID, Process.INVALID_UID); - } - }; - - private AppListAdapter mAppListAdapter; - private RecyclerView mAppList; - private View mLoadingView; - - private interface OnAppSelectedListener { - void onAppSelected(int uid); - } - - @Override - protected void onCreate(Bundle icicle) { - super.onCreate(icicle); - getActionBar().setDisplayHomeAsUpEnabled(true); - - setContentView(R.layout.app_picker_layout); - - mLoadingView = findViewById(R.id.loading_view); - - mAppList = findViewById(R.id.app_list_view); - mAppList.setLayoutManager(new LinearLayoutManager(this)); - mAppListAdapter = new AppListAdapter(AppPickerActivity.this::setSelectedUid); - mAppList.setAdapter(mAppListAdapter); - - LoaderManager.getInstance(this).initLoader(0, null, - new AppListLoaderCallbacks()); - } - - protected void setSelectedUid(int uid) { - Intent intent = new Intent(); - intent.putExtra(Intent.EXTRA_UID, uid); - setResult(RESULT_OK, intent); - finish(); - } - - @Override - public boolean onNavigateUp() { - onBackPressed(); - return true; - } - - private static class AppListLoader extends AsyncLoaderCompat<List<AppInfo>> { - private final BatteryStatsHelper mStatsHelper; - private final UserManager mUserManager; - private final PackageManager mPackageManager; - - AppListLoader(Context context) { - super(context); - mUserManager = context.getSystemService(UserManager.class); - mStatsHelper = new BatteryStatsHelper(context, false /* collectBatteryBroadcast */); - mStatsHelper.create((Bundle) null); - mStatsHelper.clearStats(); - mPackageManager = context.getPackageManager(); - } - - @Override - public List<AppInfo> loadInBackground() { - List<AppInfo> applicationList = new ArrayList<>(); - - mStatsHelper.refreshStats(BatteryStats.STATS_SINCE_CHARGED, - mUserManager.getUserProfiles()); - - final List<BatterySipper> usageList = mStatsHelper.getUsageList(); - for (BatterySipper sipper : usageList) { - AppInfo info = - AppInfoHelper.makeApplicationInfo(mPackageManager, sipper.getUid(), sipper); - if (info != null) { - applicationList.add(info); - } - } - - applicationList.sort( - Comparator.comparing((AppInfo a) -> a.powerMah).reversed()); - return applicationList; - } - - @Override - protected void onDiscardResult(List<AppInfo> result) { - } - } - - private class AppListLoaderCallbacks implements - LoaderManager.LoaderCallbacks<List<AppInfo>> { - - @NonNull - @Override - public Loader<List<AppInfo>> onCreateLoader(int id, Bundle args) { - return new AppListLoader(AppPickerActivity.this); - } - - @Override - public void onLoadFinished(@NonNull Loader<List<AppInfo>> loader, - List<AppInfo> applicationList) { - mAppListAdapter.setApplicationList(applicationList); - mAppList.setVisibility(View.VISIBLE); - mLoadingView.setVisibility(View.GONE); - } - - @Override - public void onLoaderReset(@NonNull Loader<List<AppInfo>> loader) { - } - } - - public class AppListAdapter extends RecyclerView.Adapter<AppViewHolder> { - private final OnAppSelectedListener mListener; - private List<AppInfo> mApplicationList; - - public AppListAdapter(OnAppSelectedListener listener) { - mListener = listener; - } - - void setApplicationList(List<AppInfo> applicationList) { - mApplicationList = applicationList; - notifyDataSetChanged(); - } - - @Override - public int getItemCount() { - return mApplicationList.size(); - } - - @NonNull - @Override - public AppViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int position) { - LayoutInflater layoutInflater = LayoutInflater.from(viewGroup.getContext()); - View view = layoutInflater.inflate(R.layout.app_info_layout, viewGroup, false); - return new AppViewHolder(view, mListener); - } - - @Override - public void onBindViewHolder(@NonNull AppViewHolder appViewHolder, int position) { - AppInfo item = mApplicationList.get(position); - appViewHolder.uid = item.uid; - appViewHolder.titleView.setText(item.label); - appViewHolder.uidView.setText( - String.format(Locale.getDefault(), "UID: %d", item.uid)); - appViewHolder.powerView.setText( - String.format(Locale.getDefault(), "%.1f mAh", item.powerMah)); - appViewHolder.iconView.setImageDrawable( - item.iconInfo.loadIcon(getPackageManager())); - if (item.packages != null) { - appViewHolder.packagesView.setText(item.packages); - appViewHolder.packagesView.setVisibility(View.VISIBLE); - } else { - appViewHolder.packagesView.setVisibility(View.GONE); - } - } - } - - // View Holder used when displaying apps - public static class AppViewHolder extends RecyclerView.ViewHolder - implements View.OnClickListener { - private final OnAppSelectedListener mListener; - - public int uid; - public TextView titleView; - public TextView uidView; - public ImageView iconView; - public TextView packagesView; - public TextView powerView; - - AppViewHolder(View view, OnAppSelectedListener listener) { - super(view); - mListener = listener; - view.setOnClickListener(this); - titleView = view.findViewById(android.R.id.title); - uidView = view.findViewById(R.id.uid); - iconView = view.findViewById(android.R.id.icon); - packagesView = view.findViewById(R.id.packages); - powerView = view.findViewById(R.id.power_mah); - powerView.setVisibility(View.VISIBLE); - } - - @Override - public void onClick(View v) { - mListener.onAppSelected(uid); - } - } -} diff --git a/core/tests/powertests/PowerStatsViewer/src/com/android/frameworks/core/powerstatsviewer/PowerConsumerInfoHelper.java b/core/tests/powertests/PowerStatsViewer/src/com/android/frameworks/core/powerstatsviewer/PowerConsumerInfoHelper.java new file mode 100644 index 000000000000..6fec2405b0c6 --- /dev/null +++ b/core/tests/powertests/PowerStatsViewer/src/com/android/frameworks/core/powerstatsviewer/PowerConsumerInfoHelper.java @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2020 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.frameworks.core.powerstatsviewer; + +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.os.Process; + +import androidx.annotation.NonNull; + +import com.android.internal.os.BatterySipper; + +import java.util.Locale; + +class PowerConsumerInfoHelper { + + private static final String SYSTEM_SERVER_PACKAGE_NAME = "android"; + + public static class PowerConsumerInfo { + public String id; + public CharSequence label; + public double powerMah; + public ApplicationInfo iconInfo; + public CharSequence packages; + public CharSequence details; + } + + @NonNull + public static PowerConsumerInfo makePowerConsumerInfo(PackageManager packageManager, + @NonNull BatterySipper sipper) { + PowerConsumerInfo info = new PowerConsumerInfo(); + info.id = PowerStatsData.powerConsumerId(sipper); + sipper.sumPower(); + info.powerMah = sipper.totalSmearedPowerMah; + switch (sipper.drainType) { + case APP: { + int uid = sipper.getUid(); + info.details = String.format("UID: %d", uid); + String packageWithHighestDrain = sipper.packageWithHighestDrain; + if (uid == Process.ROOT_UID) { + info.label = "<root>"; + } else { + String[] packages = packageManager.getPackagesForUid(uid); + String primaryPackageName = null; + if (uid == Process.SYSTEM_UID) { + primaryPackageName = SYSTEM_SERVER_PACKAGE_NAME; + } else if (packages != null) { + for (String name : packages) { + primaryPackageName = name; + if (name.equals(packageWithHighestDrain)) { + break; + } + } + } + + if (primaryPackageName != null) { + try { + ApplicationInfo applicationInfo = + packageManager.getApplicationInfo(primaryPackageName, 0); + info.label = applicationInfo.loadLabel(packageManager); + info.iconInfo = applicationInfo; + } catch (PackageManager.NameNotFoundException e) { + info.label = primaryPackageName; + } + } else if (packageWithHighestDrain != null) { + info.label = packageWithHighestDrain; + } + + if (packages != null && packages.length > 0) { + StringBuilder sb = new StringBuilder(); + if (primaryPackageName != null) { + sb.append(primaryPackageName); + } + for (String packageName : packages) { + if (packageName.equals(primaryPackageName)) { + continue; + } + + if (sb.length() != 0) { + sb.append(", "); + } + sb.append(packageName); + } + + info.packages = sb; + } + } + break; + } + case USER: + info.label = "User"; + info.details = String.format(Locale.getDefault(), "User ID: %d", sipper.userId); + break; + case AMBIENT_DISPLAY: + info.label = "Ambient display"; + break; + case BLUETOOTH: + info.label = "Bluetooth"; + break; + case CAMERA: + info.label = "Camera"; + break; + case CELL: + info.label = "Cell"; + break; + case FLASHLIGHT: + info.label = "Flashlight"; + break; + case IDLE: + info.label = "Idle"; + break; + case MEMORY: + info.label = "Memory"; + break; + case OVERCOUNTED: + info.label = "Overcounted"; + break; + case PHONE: + info.label = "Phone"; + break; + case SCREEN: + info.label = "Screen"; + break; + case UNACCOUNTED: + info.label = "Unaccounted"; + break; + case WIFI: + info.label = "WiFi"; + break; + } + // Default the app icon to System Server. This includes root, dex2oat and other UIDs. + if (info.iconInfo == null) { + try { + info.iconInfo = + packageManager.getApplicationInfo(SYSTEM_SERVER_PACKAGE_NAME, 0); + } catch (PackageManager.NameNotFoundException nameNotFoundException) { + // Won't happen + } + } + return info; + } +} diff --git a/core/tests/powertests/PowerStatsViewer/src/com/android/frameworks/core/powerstatsviewer/PowerConsumerPickerActivity.java b/core/tests/powertests/PowerStatsViewer/src/com/android/frameworks/core/powerstatsviewer/PowerConsumerPickerActivity.java new file mode 100644 index 000000000000..f56d113980c8 --- /dev/null +++ b/core/tests/powertests/PowerStatsViewer/src/com/android/frameworks/core/powerstatsviewer/PowerConsumerPickerActivity.java @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2020 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.frameworks.core.powerstatsviewer; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; + +import androidx.activity.result.contract.ActivityResultContract; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentActivity; +import androidx.fragment.app.FragmentStatePagerAdapter; +import androidx.viewpager.widget.ViewPager; + +import com.google.android.material.tabs.TabLayout; + +/** + * Picker, showing a sorted lists of applications and other types of entities consuming power. + * Returns the selected entity ID or null. + */ +public class PowerConsumerPickerActivity extends FragmentActivity { + + public static final ActivityResultContract<Void, String> CONTRACT = + new ActivityResultContract<Void, String>() { + @NonNull + @Override + public Intent createIntent(@NonNull Context context, Void aVoid) { + return new Intent(context, PowerConsumerPickerActivity.class); + } + + @Override + public String parseResult(int resultCode, @Nullable Intent intent) { + if (resultCode != RESULT_OK || intent == null) { + return null; + } + return intent.getStringExtra(Intent.EXTRA_RETURN_RESULT); + } + }; + + @Override + protected void onCreate(Bundle icicle) { + super.onCreate(icicle); + getActionBar().setDisplayHomeAsUpEnabled(true); + + setContentView(R.layout.power_consumer_picker_activity_layout); + + ViewPager viewPager = findViewById(R.id.pager); + + FragmentStatePagerAdapter adapter = new FragmentStatePagerAdapter( + getSupportFragmentManager()) { + + @Override + public int getCount() { + return 2; + } + + @NonNull + @Override + public Fragment getItem(int position) { + switch (position) { + case 0: + return new PowerConsumerPickerFragment( + PowerConsumerPickerFragment.PICKER_TYPE_APP); + case 1: + default: + return new PowerConsumerPickerFragment( + PowerConsumerPickerFragment.PICKER_TYPE_DRAIN); + } + } + + @Override + public CharSequence getPageTitle(int position) { + switch (position) { + case 0: + return "Apps"; + case 1: + return "Drains"; + } + return null; + } + }; + + viewPager.setAdapter(adapter); + TabLayout tabLayout = findViewById(R.id.tab_layout); + tabLayout.setupWithViewPager(viewPager); + } + + public void setSelectedPowerConsumer(String id) { + Intent intent = new Intent(); + intent.putExtra(Intent.EXTRA_RETURN_RESULT, id); + setResult(RESULT_OK, intent); + finish(); + } + + @Override + public boolean onNavigateUp() { + onBackPressed(); + return true; + } +} diff --git a/core/tests/powertests/PowerStatsViewer/src/com/android/frameworks/core/powerstatsviewer/PowerConsumerPickerFragment.java b/core/tests/powertests/PowerStatsViewer/src/com/android/frameworks/core/powerstatsviewer/PowerConsumerPickerFragment.java new file mode 100644 index 000000000000..25225b87f602 --- /dev/null +++ b/core/tests/powertests/PowerStatsViewer/src/com/android/frameworks/core/powerstatsviewer/PowerConsumerPickerFragment.java @@ -0,0 +1,256 @@ +/* + * Copyright (C) 2008 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.frameworks.core.powerstatsviewer; + +import android.content.Context; +import android.content.pm.PackageManager; +import android.os.BatteryStats; +import android.os.Bundle; +import android.os.UserHandle; +import android.os.UserManager; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.loader.app.LoaderManager; +import androidx.loader.content.Loader; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.android.frameworks.core.powerstatsviewer.PowerConsumerInfoHelper.PowerConsumerInfo; +import com.android.internal.os.BatterySipper; +import com.android.internal.os.BatteryStatsHelper; +import com.android.settingslib.utils.AsyncLoaderCompat; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Locale; + +/** + * Picker, showing a sorted lists of applications or other types of entities consuming power. + * Returns the selected entity ID or null. + */ +public class PowerConsumerPickerFragment extends Fragment { + private static final String TAG = "AppPicker"; + + public static final String PICKER_TYPE = "pickertype"; + + public static final int PICKER_TYPE_APP = 0; + public static final int PICKER_TYPE_DRAIN = 1; + + private PowerConsumerListAdapter mPowerConsumerListAdapter; + private RecyclerView mAppList; + private View mLoadingView; + + private interface OnPowerConsumerSelectedListener { + void onPowerConsumerSelected(String uid); + } + + public PowerConsumerPickerFragment(int pickerType) { + Bundle args = new Bundle(); + args.putInt(PICKER_TYPE, pickerType); + setArguments(args); + } + + public PowerConsumerPickerFragment() { + } + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, + @Nullable Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.power_consumer_picker_layout, container, false); + mLoadingView = view.findViewById(R.id.loading_view); + + mAppList = view.findViewById(R.id.list_view); + mAppList.setLayoutManager(new LinearLayoutManager(getContext())); + mPowerConsumerListAdapter = new PowerConsumerListAdapter( + PowerConsumerPickerFragment.this::setSelectedPowerConsumer); + mAppList.setAdapter(mPowerConsumerListAdapter); + + LoaderManager.getInstance(this).initLoader(0, getArguments(), + new PowerConsumerListLoaderCallbacks()); + return view; + } + + public void setSelectedPowerConsumer(String id) { + ((PowerConsumerPickerActivity) getActivity()).setSelectedPowerConsumer(id); + } + + private static class PowerConsumerListLoader extends + AsyncLoaderCompat<List<PowerConsumerInfo>> { + private final BatteryStatsHelper mStatsHelper; + private final int mPickerType; + private final UserManager mUserManager; + private final PackageManager mPackageManager; + + PowerConsumerListLoader(Context context, int pickerType) { + super(context); + mUserManager = context.getSystemService(UserManager.class); + mStatsHelper = new BatteryStatsHelper(context, false /* collectBatteryBroadcast */); + mPickerType = pickerType; + mStatsHelper.create((Bundle) null); + mStatsHelper.clearStats(); + mPackageManager = context.getPackageManager(); + } + + @Override + public List<PowerConsumerInfo> loadInBackground() { + List<PowerConsumerInfoHelper.PowerConsumerInfo> powerConsumerList = new ArrayList<>(); + + mStatsHelper.refreshStats(BatteryStats.STATS_SINCE_CHARGED, UserHandle.myUserId()); + + final List<BatterySipper> usageList = mStatsHelper.getUsageList(); + for (BatterySipper sipper : usageList) { + switch (mPickerType) { + case PICKER_TYPE_APP: + if (sipper.drainType != BatterySipper.DrainType.APP) { + continue; + } + break; + case PICKER_TYPE_DRAIN: + default: + if (sipper.drainType == BatterySipper.DrainType.APP) { + continue; + } + } + + powerConsumerList.add( + PowerConsumerInfoHelper.makePowerConsumerInfo(mPackageManager, sipper)); + } + + powerConsumerList.sort( + Comparator.comparing((PowerConsumerInfo a) -> a.powerMah).reversed()); + return powerConsumerList; + } + + @Override + protected void onDiscardResult(List<PowerConsumerInfo> result) { + } + } + + private class PowerConsumerListLoaderCallbacks implements + LoaderManager.LoaderCallbacks<List<PowerConsumerInfo>> { + + @NonNull + @Override + public Loader<List<PowerConsumerInfo>> onCreateLoader(int id, Bundle args) { + return new PowerConsumerListLoader(getContext(), args.getInt(PICKER_TYPE)); + } + + @Override + public void onLoadFinished(@NonNull Loader<List<PowerConsumerInfo>> loader, + List<PowerConsumerInfoHelper.PowerConsumerInfo> powerConsumerList) { + mPowerConsumerListAdapter.setPowerConsumerList(powerConsumerList); + mAppList.setVisibility(View.VISIBLE); + mLoadingView.setVisibility(View.GONE); + } + + @Override + public void onLoaderReset( + @NonNull Loader<List<PowerConsumerInfoHelper.PowerConsumerInfo>> loader) { + } + } + + public class PowerConsumerListAdapter extends RecyclerView.Adapter<PowerConsumerViewHolder> { + private final OnPowerConsumerSelectedListener mListener; + private List<PowerConsumerInfo> mPowerConsumerList; + + public PowerConsumerListAdapter(OnPowerConsumerSelectedListener listener) { + mListener = listener; + } + + void setPowerConsumerList(List<PowerConsumerInfo> powerConsumerList) { + mPowerConsumerList = powerConsumerList; + notifyDataSetChanged(); + } + + @Override + public int getItemCount() { + return mPowerConsumerList.size(); + } + + @NonNull + @Override + public PowerConsumerViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, + int position) { + LayoutInflater layoutInflater = LayoutInflater.from(viewGroup.getContext()); + View view = layoutInflater.inflate(R.layout.power_consumer_info_layout, viewGroup, + false); + return new PowerConsumerViewHolder(view, mListener); + } + + @Override + public void onBindViewHolder(@NonNull PowerConsumerViewHolder viewHolder, int position) { + PowerConsumerInfoHelper.PowerConsumerInfo item = mPowerConsumerList.get(position); + viewHolder.id = item.id; + viewHolder.titleView.setText(item.label); + if (item.details != null) { + viewHolder.detailsView.setText(item.details); + viewHolder.detailsView.setVisibility(View.VISIBLE); + } else { + viewHolder.detailsView.setVisibility(View.GONE); + } + viewHolder.powerView.setText( + String.format(Locale.getDefault(), "%.1f mAh", item.powerMah)); + viewHolder.iconView.setImageDrawable( + item.iconInfo.loadIcon(getContext().getPackageManager())); + if (item.packages != null) { + viewHolder.packagesView.setText(item.packages); + viewHolder.packagesView.setVisibility(View.VISIBLE); + } else { + viewHolder.packagesView.setVisibility(View.GONE); + } + } + } + + // View Holder used when displaying apps + public static class PowerConsumerViewHolder extends RecyclerView.ViewHolder + implements View.OnClickListener { + private final OnPowerConsumerSelectedListener mListener; + + public String id; + public TextView titleView; + public TextView detailsView; + public ImageView iconView; + public TextView packagesView; + public TextView powerView; + + PowerConsumerViewHolder(View view, OnPowerConsumerSelectedListener listener) { + super(view); + mListener = listener; + view.setOnClickListener(this); + titleView = view.findViewById(android.R.id.title); + detailsView = view.findViewById(R.id.details); + iconView = view.findViewById(android.R.id.icon); + packagesView = view.findViewById(R.id.packages); + powerView = view.findViewById(R.id.power_mah); + powerView.setVisibility(View.VISIBLE); + } + + @Override + public void onClick(View v) { + mListener.onPowerConsumerSelected(id); + } + } +} diff --git a/core/tests/powertests/PowerStatsViewer/src/com/android/frameworks/core/powerstatsviewer/PowerStatsData.java b/core/tests/powertests/PowerStatsViewer/src/com/android/frameworks/core/powerstatsviewer/PowerStatsData.java index 09f20baf499c..099ee22b12e4 100644 --- a/core/tests/powertests/PowerStatsViewer/src/com/android/frameworks/core/powerstatsviewer/PowerStatsData.java +++ b/core/tests/powertests/PowerStatsViewer/src/com/android/frameworks/core/powerstatsviewer/PowerStatsData.java @@ -44,11 +44,11 @@ public class PowerStatsData { public double total; } - private final AppInfoHelper.AppInfo mAppInfo; + private final PowerConsumerInfoHelper.PowerConsumerInfo mPowerConsumerInfo; private final List<Entry> mEntries = new ArrayList<>(); public PowerStatsData(Context context, BatteryStatsHelper batteryStatsHelper, - int uid) { + String powerConsumerId) { List<BatterySipper> usageList = batteryStatsHelper.getUsageList(); double totalPowerMah = 0; @@ -81,18 +81,14 @@ public class PowerStatsData { long totalAudioTimeMs = 0; long totalVideoTimeMs = 0; - BatterySipper uidSipper = null; + BatterySipper requestedPowerConsumer = null; for (BatterySipper sipper : usageList) { if (sipper.drainType == BatterySipper.DrainType.SCREEN) { totalScreenPower = sipper.sumPower(); } - if (isHiddenDrainType(sipper.drainType)) { - continue; - } - - if (sipper.drainType == BatterySipper.DrainType.APP && sipper.getUid() == uid) { - uidSipper = sipper; + if (powerConsumerId(sipper).equals(powerConsumerId)) { + requestedPowerConsumer = sipper; } totalPowerMah += sipper.sumPower(); @@ -129,79 +125,71 @@ public class PowerStatsData { totalVideoTimeMs += sipper.videoTimeMs; } - mAppInfo = AppInfoHelper.makeApplicationInfo(context.getPackageManager(), uid, uidSipper); - - if (uidSipper == null) { + if (requestedPowerConsumer == null) { + mPowerConsumerInfo = null; return; } + mPowerConsumerInfo = PowerConsumerInfoHelper.makePowerConsumerInfo( + context.getPackageManager(), requestedPowerConsumer); + addEntry("Total power", EntryType.POWER, - uidSipper.totalSmearedPowerMah, totalSmearedPowerMah); + requestedPowerConsumer.totalSmearedPowerMah, totalSmearedPowerMah); addEntry("... excluding system", EntryType.POWER, - uidSipper.totalSmearedPowerMah, totalPowerExcludeSystemMah); + requestedPowerConsumer.totalSmearedPowerMah, totalPowerExcludeSystemMah); addEntry("Screen, smeared", EntryType.POWER, - uidSipper.screenPowerMah, totalScreenPower); + requestedPowerConsumer.screenPowerMah, totalScreenPower); addEntry("Other, smeared", EntryType.POWER, - uidSipper.proportionalSmearMah, totalProportionalSmearMah); + requestedPowerConsumer.proportionalSmearMah, totalProportionalSmearMah); addEntry("Excluding smeared", EntryType.POWER, - uidSipper.totalPowerMah, totalPowerMah); + requestedPowerConsumer.totalPowerMah, totalPowerMah); addEntry("CPU", EntryType.POWER, - uidSipper.cpuPowerMah, totalCpuPowerMah); + requestedPowerConsumer.cpuPowerMah, totalCpuPowerMah); addEntry("System services", EntryType.POWER, - uidSipper.systemServiceCpuPowerMah, totalSystemServiceCpuPowerMah); - addEntry("RAM", EntryType.POWER, - uidSipper.usagePowerMah, totalUsagePowerMah); + requestedPowerConsumer.systemServiceCpuPowerMah, totalSystemServiceCpuPowerMah); + addEntry("Usage", EntryType.POWER, + requestedPowerConsumer.usagePowerMah, totalUsagePowerMah); addEntry("Wake lock", EntryType.POWER, - uidSipper.wakeLockPowerMah, totalWakeLockPowerMah); + requestedPowerConsumer.wakeLockPowerMah, totalWakeLockPowerMah); addEntry("Mobile radio", EntryType.POWER, - uidSipper.mobileRadioPowerMah, totalMobileRadioPowerMah); + requestedPowerConsumer.mobileRadioPowerMah, totalMobileRadioPowerMah); addEntry("WiFi", EntryType.POWER, - uidSipper.wifiPowerMah, totalWifiPowerMah); + requestedPowerConsumer.wifiPowerMah, totalWifiPowerMah); addEntry("Bluetooth", EntryType.POWER, - uidSipper.bluetoothPowerMah, totalBluetoothPowerMah); + requestedPowerConsumer.bluetoothPowerMah, totalBluetoothPowerMah); addEntry("GPS", EntryType.POWER, - uidSipper.gpsPowerMah, totalGpsPowerMah); + requestedPowerConsumer.gpsPowerMah, totalGpsPowerMah); addEntry("Camera", EntryType.POWER, - uidSipper.cameraPowerMah, totalCameraPowerMah); + requestedPowerConsumer.cameraPowerMah, totalCameraPowerMah); addEntry("Flashlight", EntryType.POWER, - uidSipper.flashlightPowerMah, totalFlashlightPowerMah); + requestedPowerConsumer.flashlightPowerMah, totalFlashlightPowerMah); addEntry("Sensors", EntryType.POWER, - uidSipper.sensorPowerMah, totalSensorPowerMah); + requestedPowerConsumer.sensorPowerMah, totalSensorPowerMah); addEntry("Audio", EntryType.POWER, - uidSipper.audioPowerMah, totalAudioPowerMah); + requestedPowerConsumer.audioPowerMah, totalAudioPowerMah); addEntry("Video", EntryType.POWER, - uidSipper.videoPowerMah, totalVideoPowerMah); + requestedPowerConsumer.videoPowerMah, totalVideoPowerMah); addEntry("CPU time", EntryType.DURATION, - uidSipper.cpuTimeMs, totalCpuTimeMs); + requestedPowerConsumer.cpuTimeMs, totalCpuTimeMs); addEntry("CPU foreground time", EntryType.DURATION, - uidSipper.cpuFgTimeMs, totalCpuFgTimeMs); + requestedPowerConsumer.cpuFgTimeMs, totalCpuFgTimeMs); addEntry("Wake lock time", EntryType.DURATION, - uidSipper.wakeLockTimeMs, totalWakeLockTimeMs); + requestedPowerConsumer.wakeLockTimeMs, totalWakeLockTimeMs); addEntry("WiFi running time", EntryType.DURATION, - uidSipper.wifiRunningTimeMs, totalWifiRunningTimeMs); + requestedPowerConsumer.wifiRunningTimeMs, totalWifiRunningTimeMs); addEntry("Bluetooth time", EntryType.DURATION, - uidSipper.bluetoothRunningTimeMs, totalBluetoothRunningTimeMs); + requestedPowerConsumer.bluetoothRunningTimeMs, totalBluetoothRunningTimeMs); addEntry("GPS time", EntryType.DURATION, - uidSipper.gpsTimeMs, totalGpsTimeMs); + requestedPowerConsumer.gpsTimeMs, totalGpsTimeMs); addEntry("Camera time", EntryType.DURATION, - uidSipper.cameraTimeMs, totalCameraTimeMs); + requestedPowerConsumer.cameraTimeMs, totalCameraTimeMs); addEntry("Flashlight time", EntryType.DURATION, - uidSipper.flashlightTimeMs, totalFlashlightTimeMs); + requestedPowerConsumer.flashlightTimeMs, totalFlashlightTimeMs); addEntry("Audio time", EntryType.DURATION, - uidSipper.audioTimeMs, totalAudioTimeMs); + requestedPowerConsumer.audioTimeMs, totalAudioTimeMs); addEntry("Video time", EntryType.DURATION, - uidSipper.videoTimeMs, totalVideoTimeMs); - } - - protected boolean isHiddenDrainType(BatterySipper.DrainType drainType) { - return drainType == BatterySipper.DrainType.IDLE - || drainType == BatterySipper.DrainType.CELL - || drainType == BatterySipper.DrainType.SCREEN - || drainType == BatterySipper.DrainType.UNACCOUNTED - || drainType == BatterySipper.DrainType.OVERCOUNTED - || drainType == BatterySipper.DrainType.BLUETOOTH - || drainType == BatterySipper.DrainType.WIFI; + requestedPowerConsumer.videoTimeMs, totalVideoTimeMs); } private boolean isSystemSipper(BatterySipper sipper) { @@ -230,11 +218,15 @@ public class PowerStatsData { mEntries.add(entry); } - public AppInfoHelper.AppInfo getAppInfo() { - return mAppInfo; + public PowerConsumerInfoHelper.PowerConsumerInfo getPowerConsumerInfo() { + return mPowerConsumerInfo; } public List<Entry> getEntries() { return mEntries; } + + public static String powerConsumerId(BatterySipper sipper) { + return sipper.drainType + "|" + sipper.userId + "|" + sipper.getUid(); + } } diff --git a/core/tests/powertests/PowerStatsViewer/src/com/android/frameworks/core/powerstatsviewer/PowerStatsViewerActivity.java b/core/tests/powertests/PowerStatsViewer/src/com/android/frameworks/core/powerstatsviewer/PowerStatsViewerActivity.java index 1605e9cf1b76..78f2b9135d0c 100644 --- a/core/tests/powertests/PowerStatsViewer/src/com/android/frameworks/core/powerstatsviewer/PowerStatsViewerActivity.java +++ b/core/tests/powertests/PowerStatsViewer/src/com/android/frameworks/core/powerstatsviewer/PowerStatsViewerActivity.java @@ -20,7 +20,7 @@ import android.content.Context; import android.content.SharedPreferences; import android.os.BatteryStats; import android.os.Bundle; -import android.os.Process; +import android.os.UserHandle; import android.os.UserManager; import android.view.LayoutInflater; import android.view.View; @@ -46,15 +46,15 @@ import java.util.Locale; public class PowerStatsViewerActivity extends ComponentActivity { private static final int POWER_STATS_REFRESH_RATE_MILLIS = 60 * 1000; - public static final String PREF_SELECTED_UID = "selectedUid"; - private static final String LOADER_ARG_UID = "uid"; + public static final String PREF_SELECTED_POWER_CONSUMER = "powerConsumerId"; + private static final String LOADER_ARG_POWER_CONSUMER_ID = "powerConsumerId"; private PowerStatsDataAdapter mPowerStatsDataAdapter; private Runnable mPowerStatsRefresh = this::periodicPowerStatsRefresh; private SharedPreferences mSharedPref; - private int mUid = Process.INVALID_UID; + private String mPowerConsumerId; private TextView mTitleView; - private TextView mUidView; + private TextView mDetailsView; private ImageView mIconView; private TextView mPackagesView; private RecyclerView mPowerStatsDataView; @@ -73,7 +73,7 @@ public class PowerStatsViewerActivity extends ComponentActivity { appCard.setOnClickListener((e) -> startAppPicker()); mTitleView = findViewById(android.R.id.title); - mUidView = findViewById(R.id.uid); + mDetailsView = findViewById(R.id.details); mIconView = findViewById(android.R.id.icon); mPackagesView = findViewById(R.id.packages); @@ -85,9 +85,9 @@ public class PowerStatsViewerActivity extends ComponentActivity { mLoadingView = findViewById(R.id.loading_view); mEmptyView = findViewById(R.id.empty_view); - mUid = mSharedPref.getInt(PREF_SELECTED_UID, Process.INVALID_UID); + mPowerConsumerId = mSharedPref.getString(PREF_SELECTED_POWER_CONSUMER, null); loadPowerStats(); - if (mUid == Process.INVALID_UID) { + if (mPowerConsumerId == null) { startAppPicker(); } } @@ -105,18 +105,18 @@ public class PowerStatsViewerActivity extends ComponentActivity { } private void startAppPicker() { - registerForActivityResult(AppPickerActivity.CONTRACT, this::onApplicationSelected) + registerForActivityResult(PowerConsumerPickerActivity.CONTRACT, this::onApplicationSelected) .launch(null); } - private void onApplicationSelected(int uid) { - if (uid == -1) { - if (mUid == Process.INVALID_UID) { + private void onApplicationSelected(String powerConsumerId) { + if (powerConsumerId == null) { + if (mPowerConsumerId == null) { finish(); } } else { - mUid = uid; - mSharedPref.edit().putInt(PREF_SELECTED_UID, mUid).apply(); + mPowerConsumerId = powerConsumerId; + mSharedPref.edit().putString(PREF_SELECTED_POWER_CONSUMER, mPowerConsumerId).apply(); mLoadingView.setVisibility(View.VISIBLE); loadPowerStats(); } @@ -129,18 +129,18 @@ public class PowerStatsViewerActivity extends ComponentActivity { private void loadPowerStats() { Bundle args = new Bundle(); - args.putInt(LOADER_ARG_UID, mUid); + args.putString(LOADER_ARG_POWER_CONSUMER_ID, mPowerConsumerId); LoaderManager.getInstance(this).restartLoader(0, args, new PowerStatsDataLoaderCallbacks()); } private static class PowerStatsDataLoader extends AsyncLoaderCompat<PowerStatsData> { - private final int mUid; + private final String mPowerConsumerId; private final BatteryStatsHelper mBatteryStatsHelper; private final UserManager mUserManager; - PowerStatsDataLoader(Context context, int uid) { + PowerStatsDataLoader(Context context, String powerConsumerId) { super(context); - mUid = uid; + mPowerConsumerId = powerConsumerId; mUserManager = context.getSystemService(UserManager.class); mBatteryStatsHelper = new BatteryStatsHelper(context, false /* collectBatteryBroadcast */); @@ -151,8 +151,8 @@ public class PowerStatsViewerActivity extends ComponentActivity { @Override public PowerStatsData loadInBackground() { mBatteryStatsHelper.refreshStats(BatteryStats.STATS_SINCE_CHARGED, - mUserManager.getUserProfiles()); - return new PowerStatsData(getContext(), mBatteryStatsHelper, mUid); + UserHandle.myUserId()); + return new PowerStatsData(getContext(), mBatteryStatsHelper, mPowerConsumerId); } @Override @@ -165,27 +165,38 @@ public class PowerStatsViewerActivity extends ComponentActivity { @Override public Loader<PowerStatsData> onCreateLoader(int id, Bundle args) { return new PowerStatsDataLoader(PowerStatsViewerActivity.this, - args.getInt(LOADER_ARG_UID, Process.INVALID_UID)); + args.getString(LOADER_ARG_POWER_CONSUMER_ID)); } @Override public void onLoadFinished(@NonNull Loader<PowerStatsData> loader, PowerStatsData powerStatsData) { - AppInfoHelper.AppInfo appInfo = powerStatsData.getAppInfo(); - mTitleView.setText(appInfo.label); - mUidView.setText(String.format(Locale.getDefault(), "UID: %d", appInfo.uid)); - mIconView.setImageDrawable(appInfo.iconInfo.loadIcon(getPackageManager())); - - if (appInfo.packages != null) { - mPackagesView.setText(appInfo.packages); - mPackagesView.setVisibility(View.VISIBLE); - } else { + PowerConsumerInfoHelper.PowerConsumerInfo + powerConsumerInfo = powerStatsData.getPowerConsumerInfo(); + if (powerConsumerInfo == null) { + mTitleView.setText("Power consumer not found"); mPackagesView.setVisibility(View.GONE); + } else { + mTitleView.setText(powerConsumerInfo.label); + if (powerConsumerInfo.details != null) { + mDetailsView.setText(powerConsumerInfo.details); + mDetailsView.setVisibility(View.VISIBLE); + } else { + mDetailsView.setVisibility(View.GONE); + } + mIconView.setImageDrawable( + powerConsumerInfo.iconInfo.loadIcon(getPackageManager())); + + if (powerConsumerInfo.packages != null) { + mPackagesView.setText(powerConsumerInfo.packages); + mPackagesView.setVisibility(View.VISIBLE); + } else { + mPackagesView.setVisibility(View.GONE); + } } mPowerStatsDataAdapter.setEntries(powerStatsData.getEntries()); - if (powerStatsData.getEntries().isEmpty()) { mEmptyView.setVisibility(View.VISIBLE); mPowerStatsDataView.setVisibility(View.GONE); |