Merge "Move preference loading to a background thread" into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
9d77efb7e7
@@ -42,6 +42,15 @@
|
|||||||
android:key="recent_notifications_category"
|
android:key="recent_notifications_category"
|
||||||
android:title="@string/recent_notifications">
|
android:title="@string/recent_notifications">
|
||||||
<!-- Placeholder for a list of recent apps -->
|
<!-- Placeholder for a list of recent apps -->
|
||||||
|
<com.android.settings.widget.PrimarySwitchPreference
|
||||||
|
android:key="app1"
|
||||||
|
android:order="5"/>
|
||||||
|
<com.android.settings.widget.PrimarySwitchPreference
|
||||||
|
android:key="app2"
|
||||||
|
android:order="6"/>
|
||||||
|
<com.android.settings.widget.PrimarySwitchPreference
|
||||||
|
android:key="app3"
|
||||||
|
android:order="7"/>
|
||||||
|
|
||||||
<!-- See all apps button -->
|
<!-- See all apps button -->
|
||||||
<Preference
|
<Preference
|
||||||
|
@@ -49,6 +49,7 @@ import com.android.settings.widget.PrimarySwitchPreference;
|
|||||||
import com.android.settingslib.applications.ApplicationsState;
|
import com.android.settingslib.applications.ApplicationsState;
|
||||||
import com.android.settingslib.core.AbstractPreferenceController;
|
import com.android.settingslib.core.AbstractPreferenceController;
|
||||||
import com.android.settingslib.utils.StringUtil;
|
import com.android.settingslib.utils.StringUtil;
|
||||||
|
import com.android.settingslib.utils.ThreadUtils;
|
||||||
import com.android.settingslib.widget.TwoTargetPreference;
|
import com.android.settingslib.widget.TwoTargetPreference;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -70,9 +71,9 @@ public class RecentNotifyingAppsPreferenceController extends AbstractPreferenceC
|
|||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
static final String KEY_SEE_ALL = "all_notifications";
|
static final String KEY_SEE_ALL = "all_notifications";
|
||||||
|
static final String KEY_PLACEHOLDER = "app";
|
||||||
private static final int SHOW_RECENT_APP_COUNT = 3;
|
private static final int SHOW_RECENT_APP_COUNT = 3;
|
||||||
private static final int DAYS = 3;
|
private static final int DAYS = 3;
|
||||||
private static final Set<String> SKIP_SYSTEM_PACKAGES = new ArraySet<>();
|
|
||||||
|
|
||||||
private final Fragment mHost;
|
private final Fragment mHost;
|
||||||
private final PackageManager mPm;
|
private final PackageManager mPm;
|
||||||
@@ -148,13 +149,17 @@ public class RecentNotifyingAppsPreferenceController extends AbstractPreferenceC
|
|||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
void refreshUi(Context prefContext) {
|
void refreshUi(Context prefContext) {
|
||||||
reloadData();
|
ThreadUtils.postOnBackgroundThread(() -> {
|
||||||
final List<NotifyingApp> recentApps = getDisplayableRecentAppList();
|
reloadData();
|
||||||
if (recentApps != null && !recentApps.isEmpty()) {
|
final List<NotifyingApp> recentApps = getDisplayableRecentAppList();
|
||||||
displayRecentApps(prefContext, recentApps);
|
ThreadUtils.postOnMainThread(() -> {
|
||||||
} else {
|
if (recentApps != null && !recentApps.isEmpty()) {
|
||||||
displayOnlyAllAppsLink();
|
displayRecentApps(prefContext, recentApps);
|
||||||
}
|
} else {
|
||||||
|
displayOnlyAllAppsLink();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
@@ -198,8 +203,7 @@ public class RecentNotifyingAppsPreferenceController extends AbstractPreferenceC
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
private static String getKey(int userId, String pkg) {
|
||||||
static String getKey(int userId, String pkg) {
|
|
||||||
return userId + "|" + pkg;
|
return userId + "|" + pkg;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,19 +225,9 @@ public class RecentNotifyingAppsPreferenceController extends AbstractPreferenceC
|
|||||||
mSeeAllPref.setSummary(null);
|
mSeeAllPref.setSummary(null);
|
||||||
mSeeAllPref.setIcon(R.drawable.ic_chevron_right_24dp);
|
mSeeAllPref.setIcon(R.drawable.ic_chevron_right_24dp);
|
||||||
|
|
||||||
// Rebind prefs/avoid adding new prefs if possible. Adding/removing prefs causes jank.
|
int keyIndex = 1;
|
||||||
// Build a cached preference pool
|
|
||||||
final Map<String, PrimarySwitchPreference> appPreferences = new ArrayMap<>();
|
|
||||||
int prefCount = mCategory.getPreferenceCount();
|
|
||||||
for (int i = 0; i < prefCount; i++) {
|
|
||||||
final Preference pref = mCategory.getPreference(i);
|
|
||||||
final String key = pref.getKey();
|
|
||||||
if (!TextUtils.equals(key, KEY_SEE_ALL)) {
|
|
||||||
appPreferences.put(key, (PrimarySwitchPreference) pref);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
final int recentAppsCount = recentApps.size();
|
final int recentAppsCount = recentApps.size();
|
||||||
for (int i = 0; i < recentAppsCount; i++) {
|
for (int i = 0; i < recentAppsCount; i++, keyIndex++) {
|
||||||
final NotifyingApp app = recentApps.get(i);
|
final NotifyingApp app = recentApps.get(i);
|
||||||
// Bind recent apps to existing prefs if possible, or create a new pref.
|
// Bind recent apps to existing prefs if possible, or create a new pref.
|
||||||
final String pkgName = app.getPackage();
|
final String pkgName = app.getPackage();
|
||||||
@@ -243,20 +237,12 @@ public class RecentNotifyingAppsPreferenceController extends AbstractPreferenceC
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean rebindPref = true;
|
PrimarySwitchPreference pref = mCategory.findPreference(KEY_PLACEHOLDER + keyIndex);
|
||||||
PrimarySwitchPreference pref = appPreferences.remove(getKey(app.getUserId(),
|
|
||||||
pkgName));
|
|
||||||
if (pref == null) {
|
|
||||||
pref = new PrimarySwitchPreference(prefContext);
|
|
||||||
rebindPref = false;
|
|
||||||
}
|
|
||||||
pref.setKey(getKey(app.getUserId(), pkgName));
|
|
||||||
pref.setTitle(appEntry.label);
|
pref.setTitle(appEntry.label);
|
||||||
pref.setIcon(mIconDrawableFactory.getBadgedIcon(appEntry.info));
|
pref.setIcon(mIconDrawableFactory.getBadgedIcon(appEntry.info));
|
||||||
pref.setIconSize(TwoTargetPreference.ICON_SIZE_SMALL);
|
pref.setIconSize(TwoTargetPreference.ICON_SIZE_SMALL);
|
||||||
pref.setSummary(StringUtil.formatRelativeTime(mContext,
|
pref.setSummary(StringUtil.formatRelativeTime(mContext,
|
||||||
System.currentTimeMillis() - app.getLastNotified(), true));
|
System.currentTimeMillis() - app.getLastNotified(), true));
|
||||||
pref.setOrder(i);
|
|
||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
args.putString(AppInfoBase.ARG_PACKAGE_NAME, pkgName);
|
args.putString(AppInfoBase.ARG_PACKAGE_NAME, pkgName);
|
||||||
args.putInt(AppInfoBase.ARG_PACKAGE_UID, appEntry.info.uid);
|
args.putInt(AppInfoBase.ARG_PACKAGE_UID, appEntry.info.uid);
|
||||||
@@ -280,13 +266,10 @@ public class RecentNotifyingAppsPreferenceController extends AbstractPreferenceC
|
|||||||
pref.setChecked(
|
pref.setChecked(
|
||||||
!mNotificationBackend.getNotificationsBanned(pkgName, appEntry.info.uid));
|
!mNotificationBackend.getNotificationsBanned(pkgName, appEntry.info.uid));
|
||||||
|
|
||||||
if (!rebindPref) {
|
|
||||||
mCategory.addPreference(pref);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Remove unused prefs from pref cache pool
|
// If there are less than SHOW_RECENT_APP_COUNT recent apps, remove placeholders
|
||||||
for (Preference unusedPrefs : appPreferences.values()) {
|
for (int i = keyIndex; i <= SHOW_RECENT_APP_COUNT; i++) {
|
||||||
mCategory.removePreference(unusedPrefs);
|
mCategory.removePreferenceRecursively(KEY_PLACEHOLDER + i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -48,6 +48,7 @@ import android.service.notification.NotifyingApp;
|
|||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
|
import com.android.settings.widget.PrimarySwitchPreference;
|
||||||
import com.android.settingslib.applications.AppUtils;
|
import com.android.settingslib.applications.AppUtils;
|
||||||
import com.android.settingslib.applications.ApplicationsState;
|
import com.android.settingslib.applications.ApplicationsState;
|
||||||
import com.android.settingslib.applications.instantapps.InstantAppDataProvider;
|
import com.android.settingslib.applications.instantapps.InstantAppDataProvider;
|
||||||
@@ -80,6 +81,9 @@ public class RecentNotifyingAppsPreferenceControllerTest {
|
|||||||
private PreferenceScreen mScreen;
|
private PreferenceScreen mScreen;
|
||||||
@Mock
|
@Mock
|
||||||
private PreferenceCategory mCategory;
|
private PreferenceCategory mCategory;
|
||||||
|
private PrimarySwitchPreference mApp1;
|
||||||
|
private PrimarySwitchPreference mApp2;
|
||||||
|
private PrimarySwitchPreference mApp3;
|
||||||
@Mock
|
@Mock
|
||||||
private Preference mSeeAllPref;
|
private Preference mSeeAllPref;
|
||||||
@Mock
|
@Mock
|
||||||
@@ -115,6 +119,15 @@ public class RecentNotifyingAppsPreferenceControllerTest {
|
|||||||
mController = new RecentNotifyingAppsPreferenceController(
|
mController = new RecentNotifyingAppsPreferenceController(
|
||||||
mContext, mBackend, mIUsageStatsManager, mUserManager, mAppState, mHost);
|
mContext, mBackend, mIUsageStatsManager, mUserManager, mAppState, mHost);
|
||||||
when(mScreen.findPreference(anyString())).thenReturn(mCategory);
|
when(mScreen.findPreference(anyString())).thenReturn(mCategory);
|
||||||
|
mApp1 = new PrimarySwitchPreference(mContext);
|
||||||
|
mApp1.setKey("app1");
|
||||||
|
mApp2 = new PrimarySwitchPreference(mContext);
|
||||||
|
mApp2.setKey("app2");
|
||||||
|
mApp3 = new PrimarySwitchPreference(mContext);
|
||||||
|
mApp3.setKey("app3");
|
||||||
|
when(mCategory.findPreference("app1")).thenReturn(mApp1);
|
||||||
|
when(mCategory.findPreference("app2")).thenReturn(mApp2);
|
||||||
|
when(mCategory.findPreference("app3")).thenReturn(mApp3);
|
||||||
|
|
||||||
when(mScreen.findPreference(RecentNotifyingAppsPreferenceController.KEY_SEE_ALL))
|
when(mScreen.findPreference(RecentNotifyingAppsPreferenceController.KEY_SEE_ALL))
|
||||||
.thenReturn(mSeeAllPref);
|
.thenReturn(mSeeAllPref);
|
||||||
@@ -169,12 +182,18 @@ public class RecentNotifyingAppsPreferenceControllerTest {
|
|||||||
app2.mPackage = "pkg.class2";
|
app2.mPackage = "pkg.class2";
|
||||||
app2.mTimeStamp = System.currentTimeMillis() - 1000;
|
app2.mTimeStamp = System.currentTimeMillis() - 1000;
|
||||||
events.add(app2);
|
events.add(app2);
|
||||||
|
ApplicationsState.AppEntry app1Entry = mock(ApplicationsState.AppEntry.class);
|
||||||
|
ApplicationsState.AppEntry app2Entry = mock(ApplicationsState.AppEntry.class);
|
||||||
|
app1Entry.info = mApplicationInfo;
|
||||||
|
app1Entry.label = "app 1";
|
||||||
|
app2Entry.info = mApplicationInfo;
|
||||||
|
app2Entry.label = "app 2";
|
||||||
|
|
||||||
// app1, app2 are valid apps. app3 is invalid.
|
// app1, app2 are valid apps. app3 is invalid.
|
||||||
when(mAppState.getEntry(app.getPackageName(), UserHandle.myUserId()))
|
when(mAppState.getEntry(app.getPackageName(), UserHandle.myUserId()))
|
||||||
.thenReturn(mAppEntry);
|
.thenReturn(app1Entry);
|
||||||
when(mAppState.getEntry(app1.getPackageName(), UserHandle.myUserId()))
|
when(mAppState.getEntry(app1.getPackageName(), UserHandle.myUserId()))
|
||||||
.thenReturn(mAppEntry);
|
.thenReturn(app2Entry);
|
||||||
when(mAppState.getEntry(app2.getPackageName(), UserHandle.myUserId()))
|
when(mAppState.getEntry(app2.getPackageName(), UserHandle.myUserId()))
|
||||||
.thenReturn(null);
|
.thenReturn(null);
|
||||||
when(mPackageManager.resolveActivity(any(Intent.class), anyInt())).thenReturn(
|
when(mPackageManager.resolveActivity(any(Intent.class), anyInt())).thenReturn(
|
||||||
@@ -192,7 +211,10 @@ public class RecentNotifyingAppsPreferenceControllerTest {
|
|||||||
|
|
||||||
verify(mCategory).setTitle(R.string.recent_notifications);
|
verify(mCategory).setTitle(R.string.recent_notifications);
|
||||||
// Only add app1 & app2. app3 skipped because it's invalid app.
|
// Only add app1 & app2. app3 skipped because it's invalid app.
|
||||||
verify(mCategory, times(2)).addPreference(any(Preference.class));
|
assertThat(mApp1.getTitle()).isEqualTo(app1Entry.label);
|
||||||
|
assertThat(mApp2.getTitle()).isEqualTo(app2Entry.label);
|
||||||
|
|
||||||
|
verify(mCategory).removePreferenceRecursively(mApp3.getKey());
|
||||||
|
|
||||||
verify(mSeeAllPref).setSummary(null);
|
verify(mSeeAllPref).setSummary(null);
|
||||||
verify(mSeeAllPref).setIcon(R.drawable.ic_chevron_right_24dp);
|
verify(mSeeAllPref).setIcon(R.drawable.ic_chevron_right_24dp);
|
||||||
@@ -209,22 +231,24 @@ public class RecentNotifyingAppsPreferenceControllerTest {
|
|||||||
Event app1 = new Event();
|
Event app1 = new Event();
|
||||||
app1.mEventType = Event.NOTIFICATION_INTERRUPTION;
|
app1.mEventType = Event.NOTIFICATION_INTERRUPTION;
|
||||||
app1.mPackage = "com.foo.barinstant";
|
app1.mPackage = "com.foo.barinstant";
|
||||||
app1.mTimeStamp = System.currentTimeMillis() + 200;
|
app1.mTimeStamp = System.currentTimeMillis() - 200;
|
||||||
events.add(app1);
|
events.add(app1);
|
||||||
UsageEvents usageEvents = getUsageEvents(
|
UsageEvents usageEvents = getUsageEvents(
|
||||||
new String[] {"com.foo.bar", "com.foo.barinstant"}, events);
|
new String[] {"com.foo.bar", "com.foo.barinstant"}, events);
|
||||||
when(mIUsageStatsManager.queryEventsForUser(anyLong(), anyLong(), anyInt(), anyString()))
|
when(mIUsageStatsManager.queryEventsForUser(anyLong(), anyLong(), anyInt(), anyString()))
|
||||||
.thenReturn(usageEvents);
|
.thenReturn(usageEvents);
|
||||||
|
|
||||||
|
ApplicationsState.AppEntry appEntry = mock(ApplicationsState.AppEntry.class);
|
||||||
ApplicationsState.AppEntry app1Entry = mock(ApplicationsState.AppEntry.class);
|
ApplicationsState.AppEntry app1Entry = mock(ApplicationsState.AppEntry.class);
|
||||||
ApplicationsState.AppEntry app2Entry = mock(ApplicationsState.AppEntry.class);
|
appEntry.info = mApplicationInfo;
|
||||||
|
appEntry.label = "app 1";
|
||||||
app1Entry.info = mApplicationInfo;
|
app1Entry.info = mApplicationInfo;
|
||||||
app2Entry.info = mApplicationInfo;
|
app1Entry.label = "app 2";
|
||||||
|
|
||||||
when(mAppState.getEntry(
|
when(mAppState.getEntry(
|
||||||
app.getPackageName(), UserHandle.myUserId())).thenReturn(app1Entry);
|
app.getPackageName(), UserHandle.myUserId())).thenReturn(appEntry);
|
||||||
when(mAppState.getEntry(
|
when(mAppState.getEntry(
|
||||||
app1.getPackageName(), UserHandle.myUserId())).thenReturn(app2Entry);
|
app1.getPackageName(), UserHandle.myUserId())).thenReturn(app1Entry);
|
||||||
|
|
||||||
// Only the regular app app1 should have its intent resolve.
|
// Only the regular app app1 should have its intent resolve.
|
||||||
when(mPackageManager.resolveActivity(argThat(intentMatcher(app.getPackageName())),
|
when(mPackageManager.resolveActivity(argThat(intentMatcher(app.getPackageName())),
|
||||||
@@ -233,7 +257,7 @@ public class RecentNotifyingAppsPreferenceControllerTest {
|
|||||||
// Make sure app2 is considered an instant app.
|
// Make sure app2 is considered an instant app.
|
||||||
ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
|
ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
|
||||||
(InstantAppDataProvider) (ApplicationInfo info) -> {
|
(InstantAppDataProvider) (ApplicationInfo info) -> {
|
||||||
if (info == app2Entry.info) {
|
if (info == app1Entry.info) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
@@ -242,15 +266,10 @@ public class RecentNotifyingAppsPreferenceControllerTest {
|
|||||||
|
|
||||||
mController.displayPreference(mScreen);
|
mController.displayPreference(mScreen);
|
||||||
|
|
||||||
ArgumentCaptor<Preference> prefCaptor = ArgumentCaptor.forClass(Preference.class);
|
assertThat(mApp1.getTitle()).isEqualTo(appEntry.label);
|
||||||
verify(mCategory, times(2)).addPreference(prefCaptor.capture());
|
assertThat(mApp2.getTitle()).isEqualTo(app1Entry.label);
|
||||||
List<Preference> prefs = prefCaptor.getAllValues();
|
|
||||||
assertThat(prefs.get(1).getKey()).isEqualTo(
|
verify(mCategory).removePreferenceRecursively(mApp3.getKey());
|
||||||
RecentNotifyingAppsPreferenceController.getKey(UserHandle.myUserId(),
|
|
||||||
app.getPackageName()));
|
|
||||||
assertThat(prefs.get(0).getKey()).isEqualTo(
|
|
||||||
RecentNotifyingAppsPreferenceController.getKey(UserHandle.myUserId(),
|
|
||||||
app1.getPackageName()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -274,7 +293,7 @@ public class RecentNotifyingAppsPreferenceControllerTest {
|
|||||||
|
|
||||||
mController.displayPreference(mScreen);
|
mController.displayPreference(mScreen);
|
||||||
|
|
||||||
verify(mCategory).addPreference(argThat(summaryMatches("Just now")));
|
assertThat(mApp1.getSummary()).isEqualTo("Just now");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
Reference in New Issue
Block a user