• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

packages/apps/Settings


Commit MetaInfo

Revision8469dea09b19da45f9cf791f51c838da46954643 (tree)
Time2020-11-27 16:20:20
Authortimhypeng <timhypeng@goog...>
Commitertim peng

Log Message

Fix java.lang.ArrayIndexOutOfBoundsException in RemoteVolumeGroupController

-Caused by removing and adding preference at the same time
-Make preference operation method synchronized
-Not to update preference by removing and adding. To check session status and update its content to preference
-Post to UI thread to handle the onDeviceListUpdate() callback from framework

Bug: 170049403
Test: make -j50 RunSettingsRoboTests
Merged-In: Ibfc11e1bd99ba2e578b5d9e7dcc9132e372b68dd
Change-Id: Ibfc11e1bd99ba2e578b5d9e7dcc9132e372b68dd
(cherry picked from commit 1268629fda99896bda747a2531c6c3a4480d8cb1)

Change Summary

Incremental Difference

--- a/src/com/android/settings/notification/RemoteVolumeGroupController.java
+++ b/src/com/android/settings/notification/RemoteVolumeGroupController.java
@@ -102,43 +102,80 @@ public class RemoteVolumeGroupController extends BasePreferenceController implem
102102 mLocalMediaManager.stopScan();
103103 }
104104
105- private void refreshPreference() {
106- mPreferenceCategory.removeAll();
105+ private synchronized void refreshPreference() {
107106 if (!isAvailable()) {
108107 mPreferenceCategory.setVisible(false);
109108 return;
110109 }
111110 final CharSequence castVolume = mContext.getText(R.string.remote_media_volume_option_title);
112111 mPreferenceCategory.setVisible(true);
113-
114112 for (RoutingSessionInfo info : mRoutingSessionInfos) {
115- if (mPreferenceCategory.findPreference(info.getId()) != null) {
116- continue;
113+ final CharSequence appName = Utils.getApplicationLabel(mContext,
114+ info.getClientPackageName());
115+ RemoteVolumeSeekBarPreference seekBarPreference = mPreferenceCategory.findPreference(
116+ info.getId());
117+ if (seekBarPreference != null) {
118+ // Update slider
119+ if (seekBarPreference.getProgress() != info.getVolume()) {
120+ seekBarPreference.setProgress(info.getVolume());
121+ }
122+ } else {
123+ // Add slider
124+ seekBarPreference = new RemoteVolumeSeekBarPreference(mContext);
125+ seekBarPreference.setKey(info.getId());
126+ seekBarPreference.setTitle(castVolume);
127+ seekBarPreference.setMax(info.getVolumeMax());
128+ seekBarPreference.setProgress(info.getVolume());
129+ seekBarPreference.setMin(0);
130+ seekBarPreference.setOnPreferenceChangeListener(this);
131+ seekBarPreference.setIcon(R.drawable.ic_volume_remote);
132+ mPreferenceCategory.addPreference(seekBarPreference);
117133 }
118- final CharSequence appName = Utils.getApplicationLabel(
119- mContext, info.getClientPackageName());
120- final CharSequence outputTitle = mContext.getString(R.string.media_output_label_title,
121- appName);
122- // Add slider
123- final RemoteVolumeSeekBarPreference seekBarPreference =
124- new RemoteVolumeSeekBarPreference(mContext);
125- seekBarPreference.setKey(info.getId());
126- seekBarPreference.setTitle(castVolume);
127- seekBarPreference.setMax(info.getVolumeMax());
128- seekBarPreference.setProgress(info.getVolume());
129- seekBarPreference.setMin(0);
130- seekBarPreference.setOnPreferenceChangeListener(this);
131- seekBarPreference.setIcon(R.drawable.ic_volume_remote);
132- mPreferenceCategory.addPreference(seekBarPreference);
133- // Add output indicator
134+
135+ Preference switcherPreference = mPreferenceCategory.findPreference(
136+ SWITCHER_PREFIX + info.getId());
134137 final boolean isMediaOutputDisabled = Utils.isMediaOutputDisabled(
135138 mRouterManager, info.getClientPackageName());
136- final Preference preference = new Preference(mContext);
137- preference.setKey(SWITCHER_PREFIX + info.getId());
138- preference.setTitle(isMediaOutputDisabled ? appName : outputTitle);
139- preference.setSummary(info.getName());
140- preference.setEnabled(!isMediaOutputDisabled);
141- mPreferenceCategory.addPreference(preference);
139+ final CharSequence outputTitle = mContext.getString(R.string.media_output_label_title,
140+ appName);
141+ if (switcherPreference != null) {
142+ // Update output indicator
143+ switcherPreference.setTitle(isMediaOutputDisabled ? appName : outputTitle);
144+ switcherPreference.setSummary(info.getName());
145+ switcherPreference.setEnabled(!isMediaOutputDisabled);
146+ } else {
147+ // Add output indicator
148+ switcherPreference = new Preference(mContext);
149+ switcherPreference.setKey(SWITCHER_PREFIX + info.getId());
150+ switcherPreference.setTitle(isMediaOutputDisabled ? appName : outputTitle);
151+ switcherPreference.setSummary(info.getName());
152+ switcherPreference.setEnabled(!isMediaOutputDisabled);
153+ mPreferenceCategory.addPreference(switcherPreference);
154+ }
155+ }
156+
157+ // Check and remove non-active session preference
158+ // There is a pair of preferences for each session. First one is a seekBar preference.
159+ // The second one shows the session information and provide an entry-point to launch output
160+ // switcher. It is unnecessary to go through all preferences. It is fine ignore the second
161+ // preference and only to check the seekBar's key value.
162+ for (int i = 0; i < mPreferenceCategory.getPreferenceCount(); i = i + 2) {
163+ final Preference preference = mPreferenceCategory.getPreference(i);
164+ boolean isActive = false;
165+ for (RoutingSessionInfo info : mRoutingSessionInfos) {
166+ if (TextUtils.equals(preference.getKey(), info.getId())) {
167+ isActive = true;
168+ break;
169+ }
170+ }
171+ if (isActive) {
172+ continue;
173+ }
174+ final Preference switcherPreference = mPreferenceCategory.getPreference(i + 1);
175+ if (switcherPreference != null) {
176+ mPreferenceCategory.removePreference(preference);
177+ mPreferenceCategory.removePreference(switcherPreference);
178+ }
142179 }
143180 }
144181
@@ -181,8 +218,10 @@ public class RemoteVolumeGroupController extends BasePreferenceController implem
181218 // Preference group is not ready.
182219 return;
183220 }
184- initRemoteMediaSession();
185- refreshPreference();
221+ ThreadUtils.postOnMainThread(() -> {
222+ initRemoteMediaSession();
223+ refreshPreference();
224+ });
186225 }
187226
188227 @Override