diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-07-07 05:28:40 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-07-07 05:28:40 +0000 |
commit | 582fa8f7d317c2ece43d04c42ec7d15db23cbce5 (patch) | |
tree | 801e5153963a9a347f13082c836e331d5a8e3760 | |
parent | 8b2cc74c9ad4d049aceada86225e5d0c22d2d846 (diff) | |
parent | 4eb7b888ab394100643c6500e06e3b31f1780760 (diff) | |
download | TvSettings-aml_tz5_341510010.tar.gz |
Snap for 10453563 from 4eb7b888ab394100643c6500e06e3b31f1780760 to mainline-tzdata5-releaseaml_tz5_341510050aml_tz5_341510010aml_tz5_341510010
Change-Id: I4895ad412593f7eab35363332240542322685ffc
15 files changed, 419 insertions, 218 deletions
diff --git a/Settings/AndroidManifest.xml b/Settings/AndroidManifest.xml index d077ad99d..db2d4cec2 100644 --- a/Settings/AndroidManifest.xml +++ b/Settings/AndroidManifest.xml @@ -1304,8 +1304,17 @@ </intent-filter> </activity> - <service android:name=".device.eco.EnergyModesService" - android:exported="true" /> + <service android:name=".device.eco.EnergyModesStatsLogJobService" + android:permission="android.permission.BIND_JOB_SERVICE" /> + + <provider + android:name=".device.eco.EnergyModesContentProvider" + android:authorities="com.android.tv.settings.device.eco.energymodes" + android:exported="true"> + <intent-filter> + <action android:name="com.android.tv.settings.ENERGY_MODES_PROVIDER"/> + </intent-filter> + </provider> <activity android:name=".device.eco.EnergyModesActivity" diff --git a/Settings/res/values/energy-modes.xml b/Settings/res/values/energy-modes.xml index 50a1374e0..182796205 100644 --- a/Settings/res/values/energy-modes.xml +++ b/Settings/res/values/energy-modes.xml @@ -21,6 +21,9 @@ If false, falls back to a toggle to enable/disable Low Power Standby if LPS is supported. --> <bool name="enable_energy_modes">true</bool> + <!-- The default energy mode, used if none has been set yet. --> + <string name="default_energy_mode" translatable="false">@null</string> + <!-- Energy mode: Low --> <eat-comment /> diff --git a/Settings/res/values/integers.xml b/Settings/res/values/integers.xml index a65838fab..68960fc92 100644 --- a/Settings/res/values/integers.xml +++ b/Settings/res/values/integers.xml @@ -14,6 +14,9 @@ limitations under the License. --> <resources> + <!-- Reserve all the job ids in TvSettings --> + <integer name="job_energy_modes_stats_log">100</integer> + <!-- Pin dialog --> <integer name="pin_dialog_anim_duration">250</integer> <integer name="pin_dialog_enter_offset_y">32</integer> diff --git a/Settings/res/values/strings.xml b/Settings/res/values/strings.xml index 29245e7bf..22209724f 100644 --- a/Settings/res/values/strings.xml +++ b/Settings/res/values/strings.xml @@ -579,7 +579,7 @@ <!-- Description of resolution mode that is shown on the side panel when user is scrolling through resolution modes. It lists all HDR types that this mode supports. [CHAR LIMIT=300]--> - <string name="resolution_hdr_description_info">This mode supports %1$s. On some TVs, you may + <string name="resolution_hdr_description_info">This mode supports: %1$s\nOn some TVs, you may need to turn on Enhanced HDMI to enable more HDR formats. Check your TV settings to see if this is supported.</string> <!-- Cancel button title for dialog that is shown when user changes the resolution. @@ -899,10 +899,8 @@ <string name="do_disclosure_with_name">This device is managed by <xliff:g id="organization_name" example="Foo, Inc.">%s</xliff:g>.</string> <!-- Message indicating that the device is enterprise-managed: Space that separates the main text and the "learn more" link that follows it. [CHAR LIMIT=NONE] --> <string name="do_disclosure_learn_more_separator">" "</string> - <!-- A word separator (e.g. a comma), indicating a pause between parts of a sentence or separating items in a list. [CHAR LIMIT=NONE] --> - <string name="word_separator">,</string> - <!-- A space, used for separating words --> - <string name="space_separator">" "</string> + <!-- An HDR capability[CHAR LIMIT=NONE] --> + <string name="hdr_capability">- %1$s</string> <!-- Button label to allow the user to view additional information [CHAR LIMIT=NONE BACKUP_MESSAGE_ID=2416766240581561009] --> <string name="learn_more">Learn more</string> diff --git a/Settings/src/com/android/tv/settings/TvSettingsApplication.java b/Settings/src/com/android/tv/settings/TvSettingsApplication.java index 5a62e5bc9..2e88e2930 100644 --- a/Settings/src/com/android/tv/settings/TvSettingsApplication.java +++ b/Settings/src/com/android/tv/settings/TvSettingsApplication.java @@ -20,6 +20,8 @@ import android.app.Application; import androidx.annotation.Nullable; +import com.android.tv.settings.device.eco.EnergyModesStatsLogJobService; + /** * Application class that instantiates system sound player singleton so sound effects are only * loaded once and shared between components. @@ -33,6 +35,8 @@ public class TvSettingsApplication extends Application { if (getResources().getBoolean(R.bool.config_enableSystemSounds)) { mSystemSoundsPlayer = new SystemSoundsPlayer(this); } + + EnergyModesStatsLogJobService.scheduleEnergyModesStatsLog(this); } @Nullable diff --git a/Settings/src/com/android/tv/settings/device/apps/specialaccess/NotificationAccess.java b/Settings/src/com/android/tv/settings/device/apps/specialaccess/NotificationAccess.java index 2caef3d1d..df13211d6 100644 --- a/Settings/src/com/android/tv/settings/device/apps/specialaccess/NotificationAccess.java +++ b/Settings/src/com/android/tv/settings/device/apps/specialaccess/NotificationAccess.java @@ -49,6 +49,8 @@ import java.util.List; public class NotificationAccess extends SettingsPreferenceFragment { private static final String TAG = "NotificationAccess"; + private static final int MAX_CN_LENGTH = 500; + private static final String HEADER_KEY = "header"; private static final String DEFAULT_PACKAGES_SEPARATOR = ":"; @@ -76,6 +78,12 @@ public class NotificationAccess extends SettingsPreferenceFragment { .setIntentAction(NotificationListenerService.SERVICE_INTERFACE) .setPermission(android.Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE) .setNoun("notification listener") + .setValidator(info -> { + if (info.getComponentName().flattenToString().length() > MAX_CN_LENGTH) { + return false; + } + return true; + }) .build(); mServiceListing.addCallback(this::updateList); } diff --git a/Settings/src/com/android/tv/settings/device/displaysound/ResolutionSelectionFragment.java b/Settings/src/com/android/tv/settings/device/displaysound/ResolutionSelectionFragment.java index b7426e7d0..db515ba65 100644 --- a/Settings/src/com/android/tv/settings/device/displaysound/ResolutionSelectionFragment.java +++ b/Settings/src/com/android/tv/settings/device/displaysound/ResolutionSelectionFragment.java @@ -169,7 +169,8 @@ public class ResolutionSelectionFragment extends PreferenceControllerFragment { mode.getPhysicalWidth(), mode.getPhysicalHeight()), ResolutionSelectionUtils.getRefreshRateString(mode.getRefreshRate())); - String summary = mode.getPhysicalWidth() + " x " + mode.getPhysicalHeight(); + String summary = ResolutionSelectionUtils.getResolutionSummary(mode.getPhysicalWidth(), + mode.getPhysicalHeight()); RadioPreference pref = new RadioPreference(getContext()); pref.setTitle(title); pref.setSummary(summary); diff --git a/Settings/src/com/android/tv/settings/device/displaysound/ResolutionSelectionInfo.java b/Settings/src/com/android/tv/settings/device/displaysound/ResolutionSelectionInfo.java index 73463b2f4..3f3c9ff11 100644 --- a/Settings/src/com/android/tv/settings/device/displaysound/ResolutionSelectionInfo.java +++ b/Settings/src/com/android/tv/settings/device/displaysound/ResolutionSelectionInfo.java @@ -44,28 +44,32 @@ public class ResolutionSelectionInfo { public static class HDRInfoFragment extends ResolutionSelectionInfo.BaseInfoFragment { private String hdrTypesAsString(int[] hdrTypes) { - StringBuilder supportedTypes = new StringBuilder( - getResources().getString(R.string.hdr_format_sdr)); + StringBuilder supportedTypes = new StringBuilder(System.lineSeparator()).append( + getResources().getString(R.string.hdr_capability, + getResources().getString(R.string.hdr_format_sdr))); for (int supportedType : hdrTypes) { - supportedTypes.append(getResources().getString(R.string.word_separator)) - .append(getResources().getString( - R.string.space_separator)); + supportedTypes.append(System.lineSeparator()); switch (supportedType) { case HDR_TYPE_DOLBY_VISION: supportedTypes - .append(getResources().getString(R.string.hdr_format_dolby_vision)); + .append(getResources().getString(R.string.hdr_capability, + getResources().getString( + R.string.hdr_format_dolby_vision))); break; case HDR_TYPE_HDR10: supportedTypes - .append(getResources().getString(R.string.hdr_format_hdr10)); + .append(getResources().getString(R.string.hdr_capability, + getResources().getString(R.string.hdr_format_hdr10))); break; case HDR_TYPE_HLG: supportedTypes - .append(getResources().getString(R.string.hdr_format_hlg)); + .append(getResources().getString(R.string.hdr_capability, + getResources().getString(R.string.hdr_format_hlg))); break; case HDR_TYPE_HDR10_PLUS: supportedTypes - .append(getResources().getString(R.string.hdr_format_hdr10plus)); + .append(getResources().getString(R.string.hdr_capability, + getResources().getString(R.string.hdr_format_hdr10plus))); break; } } diff --git a/Settings/src/com/android/tv/settings/device/eco/EnergyModesContentProvider.java b/Settings/src/com/android/tv/settings/device/eco/EnergyModesContentProvider.java new file mode 100644 index 000000000..18265cde6 --- /dev/null +++ b/Settings/src/com/android/tv/settings/device/eco/EnergyModesContentProvider.java @@ -0,0 +1,215 @@ +/* + * Copyright (C) 2023 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.tv.settings.device.eco; + +import static android.Manifest.permission.MANAGE_LOW_POWER_STANDBY; + +import android.content.ContentProvider; +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.graphics.drawable.Icon; +import android.net.Uri; +import android.os.Binder; +import android.os.Bundle; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.android.tv.settings.device.eco.EnergyModesHelper.EnergyMode; + +import java.util.ArrayList; +import java.util.List; + +/** + * ContentProvider that provides methods to query and set Energy Modes. + */ +public class EnergyModesContentProvider extends ContentProvider { + /** Method to get available energy modes, default mode, and selected mode */ + private static final String METHOD_GET_ENERGY_MODES = "getEnergyModes"; + + /** + * Method to set the selected energy mode. + * Requires permission MANAGE_LOW_POWER_STANDBY. + */ + private static final String METHOD_SET_ENERGY_MODE = "setEnergyMode"; + + /** Key for a String representing the identifier of the default mode (may be null). */ + private static final String KEY_DEFAULT_MODE = "default_mode"; + + /** Key for a String representing the currently selected mode. */ + private static final String KEY_SELECTED_MODE = "selected_mode"; + + /** Key for a List of Bundle representing the available energy modes. */ + private static final String KEY_ENERGY_MODES = "energy_modes"; + + /** Key for a String representing the identifier for an energy mode. */ + private static final String KEY_IDENTIFIER = "identifier"; + + /** Key for an Icon representing the icon of an energy mode. */ + private static final String KEY_ICON = "icon"; + + /** Key for an int representing the color of an energy mode (in ARGB). */ + private static final String KEY_COLOR = "color"; + + /** Key for a String representing the title of an energy mode. */ + private static final String KEY_TITLE = "title"; + + /** Key for a String representing the subtitle of an energy mode. */ + private static final String KEY_SUBTITLE = "subtitle"; + + /** Key for a String representing the description of an energy mode. */ + private static final String KEY_DESCRIPTION = "description"; + + /** Key for a String representing a short description of an energy mode. */ + private static final String KEY_SHORT_DESCRIPTION = "short_description"; + + /** Key for a String array representing the (human-friendly) features of an energy mode. */ + private static final String KEY_FEATURES_LIST = "features_list"; + + /** Key for a String array representing the features of an energy mode. */ + private static final String KEY_FEATURES = "features"; + + @Override + public boolean onCreate() { + return true; + } + + @Nullable + @Override + public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, + @Nullable String[] selectionArgs, @Nullable String sortOrder) { + throw new UnsupportedOperationException("query operation not supported currently."); + } + + @Nullable + @Override + public String getType(@NonNull Uri uri) { + throw new UnsupportedOperationException("getType operation not supported currently."); + } + + @Nullable + @Override + public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) { + throw new UnsupportedOperationException("insert operation not supported currently."); + } + + @Override + public int delete(@NonNull Uri uri, @Nullable String selection, + @Nullable String[] selectionArgs) { + throw new UnsupportedOperationException("delete operation not supported currently."); + } + + @Override + public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, + @Nullable String[] selectionArgs) { + throw new UnsupportedOperationException("update operation not supported currently."); + } + + @Override + public Bundle call(String method, String arg, Bundle extras) { + if (METHOD_GET_ENERGY_MODES.equals(method)) { + return getEnergyModesFromBinder(); + } else if (METHOD_SET_ENERGY_MODE.equals(method)) { + return setEnergyModeFromBinder(arg); + } + + throw new IllegalArgumentException("Unknown method name"); + } + + private Bundle getEnergyModesFromBinder() { + final long ident = Binder.clearCallingIdentity(); + try { + return getEnergyModes(); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + private Bundle getEnergyModes() { + EnergyModesHelper energyModesHelper = new EnergyModesHelper(getContext()); + + final EnergyMode defaultMode = energyModesHelper.getDefaultEnergyMode(); + final EnergyMode currentMode = energyModesHelper.updateEnergyMode(); + + Bundle bundle = new Bundle(); + bundle.putString(KEY_DEFAULT_MODE, getModeIdentifier(defaultMode)); + bundle.putString(KEY_SELECTED_MODE, getModeIdentifier(currentMode)); + bundle.putParcelableList(KEY_ENERGY_MODES, getModes(energyModesHelper)); + return bundle; + } + + private Bundle setEnergyModeFromBinder(String identifier) { + getContext().enforceCallingOrSelfPermission(MANAGE_LOW_POWER_STANDBY, null); + final long ident = Binder.clearCallingIdentity(); + try { + EnergyModesHelper energyModesHelper = new EnergyModesHelper(getContext()); + EnergyMode energyMode = energyModesHelper.getEnergyMode(/* identifier= */ identifier); + if (energyMode == null) { + throw new IllegalArgumentException("Unknown energy mode: " + identifier); + } + + energyModesHelper.setEnergyMode(energyMode); + } finally { + Binder.restoreCallingIdentity(ident); + } + + return null; + } + + @Nullable + private String getModeIdentifier(@Nullable EnergyMode mode) { + if (mode == null) { + return null; + } + + return getContext().getString(mode.identifierRes); + } + + @NonNull + private List<Bundle> getModes(@NonNull EnergyModesHelper helper) { + final List<Bundle> result = new ArrayList<>(); + final List<EnergyMode> energyModes = helper.getEnergyModes(); + + for (EnergyMode mode : energyModes) { + result.add(convertEnergyModeToBundle(helper, mode)); + } + + return result; + } + + @NonNull + private Bundle convertEnergyModeToBundle( + @NonNull EnergyModesHelper helper, @NonNull EnergyMode mode) { + Context context = getContext(); + Bundle bundle = new Bundle(); + + bundle.putString(KEY_IDENTIFIER, getModeIdentifier(mode)); + bundle.putParcelable(KEY_ICON, Icon.createWithResource(context, mode.iconRes)); + bundle.putInt(KEY_COLOR, context.getColor(mode.colorRes)); + bundle.putString(KEY_TITLE, context.getString(mode.titleRes)); + bundle.putString(KEY_SUBTITLE, context.getString(mode.subtitleRes)); + bundle.putString(KEY_DESCRIPTION, context.getString(mode.infoTextRes)); + bundle.putString(KEY_SHORT_DESCRIPTION, context.getString(mode.infoTextRes)); + bundle.putStringArray(KEY_FEATURES_LIST, + context.getResources().getStringArray(mode.featuresRes)); + bundle.putStringArray(KEY_FEATURES, + helper.getAllowedFeatures(mode).toArray(new String[0])); + + return bundle; + } +} diff --git a/Settings/src/com/android/tv/settings/device/eco/EnergyModesHelper.java b/Settings/src/com/android/tv/settings/device/eco/EnergyModesHelper.java index ffa32c7fd..e8ce5efd2 100644 --- a/Settings/src/com/android/tv/settings/device/eco/EnergyModesHelper.java +++ b/Settings/src/com/android/tv/settings/device/eco/EnergyModesHelper.java @@ -330,7 +330,7 @@ public final class EnergyModesHelper { return string.split(","); } - private LowPowerStandbyPolicy getPolicy(EnergyMode mode) { + LowPowerStandbyPolicy getPolicy(EnergyMode mode) { if (!mode.enableLowPowerStandby) { return new LowPowerStandbyPolicy( mContext.getString(mode.identifierRes), @@ -410,7 +410,7 @@ public final class EnergyModesHelper { if (!areEnergyModesAvailable()) { return null; } - return getEnergyModes().get(0); + return getEnergyMode(mContext.getString(R.string.default_energy_mode)); } /** @@ -466,6 +466,10 @@ public final class EnergyModesHelper { targetEnergyMode = MODE_HIGH_ENERGY; } else { targetEnergyMode = getDefaultEnergyMode(); + if (targetEnergyMode == null) { + // Fall back to lowest energy mode if default is not set or invalid + targetEnergyMode = getEnergyModes().get(0); + } } } diff --git a/Settings/src/com/android/tv/settings/device/eco/EnergyModesService.java b/Settings/src/com/android/tv/settings/device/eco/EnergyModesService.java deleted file mode 100644 index 7f089a51a..000000000 --- a/Settings/src/com/android/tv/settings/device/eco/EnergyModesService.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (C) 2023 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.tv.settings.device.eco; - -import static android.Manifest.permission.MANAGE_LOW_POWER_STANDBY; - -import android.annotation.EnforcePermission; -import android.app.Service; -import android.content.Context; -import android.content.Intent; -import android.graphics.drawable.Icon; -import android.os.Binder; -import android.os.Bundle; -import android.os.IBinder; - -import com.android.tv.settings.device.eco.EnergyModesHelper.EnergyMode; - -import java.util.ArrayList; -import java.util.List; - -/** - * Service that provides methods to query and set Energy Modes. - */ -public class EnergyModesService extends Service { - - private BinderService mService; - - @Override - public void onCreate() { - super.onCreate(); - mService = new BinderService(getApplication()); - } - - @Override - public IBinder onBind(Intent intent) { - return mService; - } - - private class BinderService extends IEnergyModesService.Stub { - private final Context mContext; - private final EnergyModesHelper mHelper; - - BinderService(Context context) { - mContext = context; - mHelper = new EnergyModesHelper(context); - } - - @Override - public List<Bundle> getModes() { - final long ident = Binder.clearCallingIdentity(); - try { - final List<Bundle> result = new ArrayList<>(); - final List<EnergyMode> energyModes = mHelper.getEnergyModes(); - final EnergyMode currentMode = mHelper.updateEnergyMode(); - - for (EnergyMode mode : energyModes) { - result.add(convertToBundle(mode, mode == currentMode)); - } - - return result; - } finally { - Binder.restoreCallingIdentity(ident); - } - } - - private Bundle convertToBundle(EnergyMode mode, boolean selected) { - Bundle bundle = new Bundle(); - - bundle.putBoolean(KEY_SELECTED, selected); - bundle.putString(KEY_IDENTIFIER, getString(mode.identifierRes)); - bundle.putParcelable(KEY_ICON, Icon.createWithResource(mContext, mode.iconRes)); - bundle.putInt(KEY_COLOR, getColor(mode.colorRes)); - bundle.putString(KEY_TITLE, getString(mode.titleRes)); - bundle.putString(KEY_SUBTITLE, getString(mode.subtitleRes)); - bundle.putString(KEY_DESCRIPTION, getString(mode.infoTextRes)); - bundle.putString(KEY_SHORT_DESCRIPTION, getString(mode.infoTextRes)); - bundle.putStringArray(KEY_FEATURES_LIST, - getResources().getStringArray(mode.featuresRes)); - bundle.putStringArray(KEY_FEATURES, - mHelper.getAllowedFeatures(mode).toArray(new String[0])); - - return bundle; - } - - @EnforcePermission(MANAGE_LOW_POWER_STANDBY) - @Override - public void setMode(String identifier) { - super.setMode_enforcePermission(); - - final long ident = Binder.clearCallingIdentity(); - try { - final EnergyMode mode = mHelper.getEnergyMode(identifier); - if (mode == null) { - throw new IllegalArgumentException("Unknown energy mode: " + identifier); - } - mHelper.setEnergyMode(mode); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - - @Override - public String getDefaultMode() { - final long ident = Binder.clearCallingIdentity(); - try { - final EnergyMode mode = mHelper.getDefaultEnergyMode(); - if (mode == null) { - return null; - } - return getString(mode.identifierRes); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - } -} diff --git a/Settings/src/com/android/tv/settings/device/eco/EnergyModesStatsLogJobService.java b/Settings/src/com/android/tv/settings/device/eco/EnergyModesStatsLogJobService.java new file mode 100644 index 000000000..f3c416381 --- /dev/null +++ b/Settings/src/com/android/tv/settings/device/eco/EnergyModesStatsLogJobService.java @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2023 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.tv.settings.device.eco; + +import android.app.job.JobInfo; +import android.app.job.JobParameters; +import android.app.job.JobScheduler; +import android.app.job.JobService; +import android.content.ComponentName; +import android.content.Context; +import android.content.pm.PackageManager; +import android.os.PowerManager.LowPowerStandbyPolicy; +import android.util.ArraySet; +import android.util.Log; + +import com.android.settingslib.utils.ThreadUtils; +import com.android.tv.settings.R; +import com.android.tv.settings.device.eco.EnergyModesHelper.EnergyMode; +import com.android.tv.twopanelsettings.slices.TvSettingsStatsLog; + +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.TimeUnit; + +/** + * JobService to log available energy mode policies. + */ +public class EnergyModesStatsLogJobService extends JobService { + private static final String TAG = "EnergyModesStatsLogJobService"; + private static final long WRITE_STATS_FREQUENCY_MS = TimeUnit.DAYS.toMillis(6); + + /** Schedule a periodic job to log available energy mode policies. */ + public static void scheduleEnergyModesStatsLog(Context context) { + final EnergyModesHelper energyModesHelper = new EnergyModesHelper(context); + if (!energyModesHelper.areEnergyModesAvailable()) { + return; + } + + final JobScheduler jobScheduler = context.getSystemService(JobScheduler.class); + final ComponentName component = + new ComponentName(context, EnergyModesStatsLogJobService.class); + final JobInfo job = + new JobInfo.Builder(R.integer.job_energy_modes_stats_log, component) + .setPeriodic(WRITE_STATS_FREQUENCY_MS) + .setRequiresDeviceIdle(true) + .setPersisted(true) + .build(); + final JobInfo pending = jobScheduler.getPendingJob(R.integer.job_energy_modes_stats_log); + + // Don't schedule it if it already exists, to make sure it runs periodically even after + // reboot + if (pending == null && jobScheduler.schedule(job) != JobScheduler.RESULT_SUCCESS) { + Log.i(TAG, "Energy Modes stats log job service schedule failed."); + } + } + + @Override + public boolean onStartJob(JobParameters params) { + ThreadUtils.postOnBackgroundThread(() -> { + writePoliciesStatsLog(getApplicationContext()); + jobFinished(params, false /* wantsReschedule */); + }); + + return true; + } + + @Override + public boolean onStopJob(JobParameters jobParameters) { + return false; + } + + /** Writes available energy mode policies to stats log */ + public static void writePoliciesStatsLog(Context context) { + final EnergyModesHelper energyModesHelper = new EnergyModesHelper(context); + final EnergyMode current = energyModesHelper.updateEnergyMode(); + final List<EnergyMode> energyModes = energyModesHelper.getEnergyModes(); + + for (EnergyMode energyMode : energyModes) { + final LowPowerStandbyPolicy policy = energyModesHelper.getPolicy(energyMode); + TvSettingsStatsLog.write( + TvSettingsStatsLog.TV_LOW_POWER_STANDBY_POLICY, + policy.getIdentifier(), + getExemptPackageUids(context, policy), + policy.getAllowedReasons(), + policy.getAllowedFeatures().toArray(new String[0]), + energyMode == current + ); + } + } + + private static int[] getExemptPackageUids(Context context, LowPowerStandbyPolicy policy) { + final PackageManager packageManager = context.getPackageManager(); + final ArraySet<Integer> exemptUids = new ArraySet<>(); + for (String exemptPackage : policy.getExemptPackages()) { + try { + int uid = packageManager.getPackageUid(exemptPackage, PackageManager.MATCH_ALL); + exemptUids.add(uid); + } catch (PackageManager.NameNotFoundException e) { + } + } + + final int[] exemptUidsArray = new int[exemptUids.size()]; + int i = 0; + for (Integer uid : exemptUids) { + exemptUidsArray[i++] = uid; + } + + Arrays.sort(exemptUidsArray); + return exemptUidsArray; + } +} diff --git a/Settings/src/com/android/tv/settings/device/eco/IEnergyModesService.aidl b/Settings/src/com/android/tv/settings/device/eco/IEnergyModesService.aidl deleted file mode 100644 index 6f5c9269b..000000000 --- a/Settings/src/com/android/tv/settings/device/eco/IEnergyModesService.aidl +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2023 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.tv.settings.device.eco; - -import android.os.Bundle; - -/** {@hide} */ -interface IEnergyModesService { - /** Key for a boolean representing whether the energy mode is currently selected. */ - const String KEY_SELECTED = "selected"; - - /** Key for a String representing the identifier for an energy mode. */ - const String KEY_IDENTIFIER = "identifier"; - - /** Key for an Icon representing the icon of an energy mode. */ - const String KEY_ICON = "icon"; - - /** Key for an int representing the color of an energy mode (in ARGB). */ - const String KEY_COLOR = "color"; - - /** Key for a String representing the title of an energy mode. */ - const String KEY_TITLE = "title"; - - /** Key for a String representing the subtitle of an energy mode. */ - const String KEY_SUBTITLE = "subtitle"; - - /** Key for a String representing the description of an energy mode. */ - const String KEY_DESCRIPTION = "description"; - - /** Key for a String representing a short description of an energy mode. */ - const String KEY_SHORT_DESCRIPTION = "short_description"; - - /** Key for a String array representing the (human-friendly) features of an energy mode. */ - const String KEY_FEATURES_LIST = "features_list"; - - /** Key for a String array representing the features of an energy mode. */ - const String KEY_FEATURES = "features"; - - /** Returns the list of available energy modes */ - List<Bundle> getModes(); - - /** Sets the selected energy mode by the given identifier */ - @EnforcePermission("MANAGE_LOW_POWER_STANDBY") - void setMode(String identifier); - - /** Returns the identifier of the default energy mode */ - String getDefaultMode(); -} diff --git a/Settings/src/com/android/tv/settings/util/ResolutionSelectionUtils.java b/Settings/src/com/android/tv/settings/util/ResolutionSelectionUtils.java index 3c2069aa9..72150403e 100644 --- a/Settings/src/com/android/tv/settings/util/ResolutionSelectionUtils.java +++ b/Settings/src/com/android/tv/settings/util/ResolutionSelectionUtils.java @@ -16,25 +16,35 @@ package com.android.tv.settings.util; +import static java.math.RoundingMode.HALF_UP; + import android.content.Context; +import android.icu.number.LocalizedNumberFormatter; +import android.icu.number.NumberFormatter; import android.view.Display; import com.android.tv.settings.R; +import java.util.Locale; + /** This utility class for Resolution Setting **/ public class ResolutionSelectionUtils { /** - * Returns the refresh rate converted to a string. If the refresh rate has only 0s after the - * floating point, they are removed. The unit "Hz" is added to end of refresh rate. + * Returns the refresh rate converted to a string in the local language. If the refresh rate has + * only 0s after the floating point, they are removed. + * The unit "Hz" is added to end of refresh rate. */ public static String getRefreshRateString(float refreshRate) { - float roundedRefreshRate = Math.round(refreshRate * 100.0f) / 100.0f; + LocalizedNumberFormatter localizedNumberFormatter = NumberFormatter.with().roundingMode( + HALF_UP).locale(Locale.getDefault()); + double roundedRefreshRate = Math.round(refreshRate * 100.0f) / 100.0f; if (roundedRefreshRate % 1 == 0) { - return Integer.toString((int) roundedRefreshRate); + return localizedNumberFormatter.format(roundedRefreshRate).toString(); } else { - return Float.toString(roundedRefreshRate); + return String.format(Locale.getDefault(), "%.2f", + localizedNumberFormatter.format(roundedRefreshRate).toBigDecimal()); } } @@ -64,4 +74,15 @@ public class ResolutionSelectionUtils { ResolutionSelectionUtils.getRefreshRateString(mode.getRefreshRate())); return modeString; } + + /** + * Returns the resolution mode converted to a string in the local language. + * Format: width + " x " + height + */ + public static String getResolutionSummary(int physicalWidth, int physicalHeight) { + LocalizedNumberFormatter localizedNumberFormatter = NumberFormatter.with().locale( + Locale.getDefault()); + return localizedNumberFormatter.format(physicalWidth).toString() + " x " + + localizedNumberFormatter.format(physicalHeight).toString(); + } } diff --git a/TwoPanelSettingsLib/Android.bp b/TwoPanelSettingsLib/Android.bp index fa0056bc6..a944c5d30 100644 --- a/TwoPanelSettingsLib/Android.bp +++ b/TwoPanelSettingsLib/Android.bp @@ -47,8 +47,6 @@ android_library { "androidx.cardview_cardview", "statslog-tvsettings", ], - - min_sdk_version: "30", } // For the test package. |