diff --git a/src/com/android/settings/applications/appinfo/AppBatteryPreferenceController.java b/src/com/android/settings/applications/appinfo/AppBatteryPreferenceController.java index 3cb22e07b61..d69c2c880cc 100644 --- a/src/com/android/settings/applications/appinfo/AppBatteryPreferenceController.java +++ b/src/com/android/settings/applications/appinfo/AppBatteryPreferenceController.java @@ -45,6 +45,7 @@ import com.android.settings.fuelgauge.BatteryUsageStatsLoader; import com.android.settings.fuelgauge.BatteryUtils; import com.android.settings.fuelgauge.PowerUsageFeatureProvider; import com.android.settings.overlay.FeatureFactory; +import com.android.settingslib.applications.AppUtils; import com.android.settingslib.core.lifecycle.Lifecycle; import com.android.settingslib.core.lifecycle.LifecycleObserver; import com.android.settingslib.core.lifecycle.events.OnPause; @@ -71,9 +72,10 @@ public class AppBatteryPreferenceController extends BasePreferenceController BatteryDiffEntry mBatteryDiffEntry; @VisibleForTesting boolean mIsChartGraphEnabled; + @VisibleForTesting + final AppInfoDashboardFragment mParent; private Preference mPreference; - private final AppInfoDashboardFragment mParent; private String mBatteryPercent; private final String mPackageName; private final int mUid; @@ -107,6 +109,11 @@ public class AppBatteryPreferenceController extends BasePreferenceController super.displayPreference(screen); mPreference = screen.findPreference(getPreferenceKey()); mPreference.setEnabled(false); + if (!AppUtils.isAppInstalled(mParent.getAppEntry())) { + mPreference.setSummary(""); + return; + } + loadBatteryDiffEntries(); } diff --git a/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceController.java b/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceController.java index 6a254cbd8c2..4848be7763f 100644 --- a/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceController.java +++ b/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceController.java @@ -35,6 +35,7 @@ import com.android.settings.Utils; import com.android.settings.datausage.AppDataUsage; import com.android.settings.datausage.DataUsageUtils; import com.android.settingslib.AppItem; +import com.android.settingslib.applications.AppUtils; import com.android.settingslib.core.lifecycle.LifecycleObserver; import com.android.settingslib.core.lifecycle.events.OnPause; import com.android.settingslib.core.lifecycle.events.OnResume; @@ -61,6 +62,7 @@ public class AppDataUsagePreferenceController extends AppInfoPreferenceControlle @Override public void displayPreference(PreferenceScreen screen) { super.displayPreference(screen); + mPreference.setEnabled(AppUtils.isAppInstalled(mAppEntry)); } @Override diff --git a/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java b/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java index 4cf591125a3..18cb4b3b80b 100755 --- a/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java +++ b/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java @@ -154,6 +154,7 @@ public class AppInfoDashboardFragment extends DashboardFragment final TimeSpentInAppPreferenceController timeSpentInAppPreferenceController = use( TimeSpentInAppPreferenceController.class); timeSpentInAppPreferenceController.setPackageName(packageName); + timeSpentInAppPreferenceController.setParentFragment(this); timeSpentInAppPreferenceController.initLifeCycleOwner(this); use(AppDataUsagePreferenceController.class).setParentFragment(this); diff --git a/src/com/android/settings/applications/appinfo/AppInfoPreferenceControllerBase.java b/src/com/android/settings/applications/appinfo/AppInfoPreferenceControllerBase.java index c495cbc50c8..718ddb8490b 100644 --- a/src/com/android/settings/applications/appinfo/AppInfoPreferenceControllerBase.java +++ b/src/com/android/settings/applications/appinfo/AppInfoPreferenceControllerBase.java @@ -25,6 +25,7 @@ import androidx.preference.PreferenceScreen; import com.android.settings.SettingsPreferenceFragment; import com.android.settings.core.BasePreferenceController; +import com.android.settingslib.applications.ApplicationsState; /* * Abstract base controller for the app detail preferences that refresh the state when the app state @@ -35,6 +36,7 @@ public abstract class AppInfoPreferenceControllerBase extends BasePreferenceCont protected AppInfoDashboardFragment mParent; protected Preference mPreference; + protected ApplicationsState.AppEntry mAppEntry; private final Class mDetailFragmentClass; @@ -72,10 +74,12 @@ public abstract class AppInfoPreferenceControllerBase extends BasePreferenceCont public void setParentFragment(AppInfoDashboardFragment parent) { mParent = parent; parent.addToCallbackList(this); + mAppEntry = mParent.getAppEntry(); } /** * Gets the fragment class to be launched when the preference is clicked. + * * @return the fragment to launch */ protected Class getDetailFragmentClass() { @@ -84,10 +88,10 @@ public abstract class AppInfoPreferenceControllerBase extends BasePreferenceCont /** * Gets any extras that should be passed to the fragment class when the preference is clicked. + * * @return a bundle of extras to include in the launch intent */ protected Bundle getArguments() { return null; } - } diff --git a/src/com/android/settings/applications/appinfo/AppNotificationPreferenceController.java b/src/com/android/settings/applications/appinfo/AppNotificationPreferenceController.java index bc87b44a69c..a32205bdfdb 100644 --- a/src/com/android/settings/applications/appinfo/AppNotificationPreferenceController.java +++ b/src/com/android/settings/applications/appinfo/AppNotificationPreferenceController.java @@ -22,11 +22,13 @@ import android.content.Context; import android.os.Bundle; import androidx.preference.Preference; +import androidx.preference.PreferenceScreen; import com.android.settings.R; import com.android.settings.SettingsPreferenceFragment; -import com.android.settings.notification.app.AppNotificationSettings; import com.android.settings.notification.NotificationBackend; +import com.android.settings.notification.app.AppNotificationSettings; +import com.android.settingslib.applications.AppUtils; import com.android.settingslib.applications.ApplicationsState; public class AppNotificationPreferenceController extends AppInfoPreferenceControllerBase { @@ -49,6 +51,12 @@ public class AppNotificationPreferenceController extends AppInfoPreferenceContro } } + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + mPreference.setEnabled(AppUtils.isAppInstalled(mAppEntry)); + } + @Override public void updateState(Preference preference) { preference.setSummary(getNotificationSummary(mParent.getAppEntry(), mContext, mBackend)); diff --git a/src/com/android/settings/applications/appinfo/AppStoragePreferenceController.java b/src/com/android/settings/applications/appinfo/AppStoragePreferenceController.java index 4e6bf4e1428..490fa0e87b2 100644 --- a/src/com/android/settings/applications/appinfo/AppStoragePreferenceController.java +++ b/src/com/android/settings/applications/appinfo/AppStoragePreferenceController.java @@ -26,12 +26,13 @@ import androidx.annotation.VisibleForTesting; import androidx.loader.app.LoaderManager; import androidx.loader.content.Loader; import androidx.preference.Preference; +import androidx.preference.PreferenceScreen; import com.android.settings.R; import com.android.settings.SettingsPreferenceFragment; import com.android.settings.applications.AppStorageSettings; import com.android.settings.applications.FetchPackageStorageAsyncLoader; -import com.android.settingslib.applications.ApplicationsState; +import com.android.settingslib.applications.AppUtils; import com.android.settingslib.applications.StorageStatsSource; import com.android.settingslib.core.lifecycle.LifecycleObserver; import com.android.settingslib.core.lifecycle.events.OnPause; @@ -47,14 +48,22 @@ public class AppStoragePreferenceController extends AppInfoPreferenceControllerB super(context, key); } + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + mPreference.setEnabled(AppUtils.isAppInstalled(mAppEntry)); + } + @Override public void updateState(Preference preference) { - final ApplicationsState.AppEntry entry = mParent.getAppEntry(); - if (entry != null && entry.info != null) { - final boolean isExternal = - (entry.info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0; - preference.setSummary(getStorageSummary(mLastResult, isExternal)); + if (!AppUtils.isAppInstalled(mAppEntry)) { + preference.setSummary(""); + return; } + + final boolean isExternal = + (mAppEntry.info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0; + preference.setSummary(getStorageSummary(mLastResult, isExternal)); } @Override @@ -102,5 +111,4 @@ public class AppStoragePreferenceController extends AppInfoPreferenceControllerB @Override public void onLoaderReset(Loader loader) { } - } diff --git a/src/com/android/settings/applications/appinfo/TimeSpentInAppPreferenceController.java b/src/com/android/settings/applications/appinfo/TimeSpentInAppPreferenceController.java index 27d90269e3f..3682af27f2f 100644 --- a/src/com/android/settings/applications/appinfo/TimeSpentInAppPreferenceController.java +++ b/src/com/android/settings/applications/appinfo/TimeSpentInAppPreferenceController.java @@ -31,6 +31,8 @@ import androidx.preference.PreferenceScreen; import com.android.settings.applications.ApplicationFeatureProvider; import com.android.settings.core.LiveDataController; import com.android.settings.overlay.FeatureFactory; +import com.android.settingslib.applications.AppUtils; +import com.android.settingslib.applications.ApplicationsState; import java.util.List; @@ -45,6 +47,8 @@ public class TimeSpentInAppPreferenceController extends LiveDataController { private final ApplicationFeatureProvider mAppFeatureProvider; private Intent mIntent; private String mPackageName; + protected AppInfoDashboardFragment mParent; + protected ApplicationsState.AppEntry mAppEntry; public TimeSpentInAppPreferenceController(Context context, String preferenceKey) { super(context, preferenceKey); @@ -59,6 +63,14 @@ public class TimeSpentInAppPreferenceController extends LiveDataController { .putExtra(Intent.EXTRA_PACKAGE_NAME, mPackageName); } + /** + * Set a parent fragment for this controller. + */ + public void setParentFragment(AppInfoDashboardFragment parent) { + mParent = parent; + mAppEntry = mParent.getAppEntry(); + } + @Override public int getAvailabilityStatus() { if (TextUtils.isEmpty(mPackageName)) { @@ -84,6 +96,7 @@ public class TimeSpentInAppPreferenceController extends LiveDataController { if (pref != null) { pref.setIntent(mIntent); } + pref.setEnabled(AppUtils.isAppInstalled(mAppEntry)); } @Override diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/AppBatteryPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/AppBatteryPreferenceControllerTest.java index bcca0f20b6f..03b3a479895 100644 --- a/tests/robotests/src/com/android/settings/applications/appinfo/AppBatteryPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/applications/appinfo/AppBatteryPreferenceControllerTest.java @@ -28,6 +28,7 @@ import static org.mockito.Mockito.when; import android.app.AppOpsManager; import android.content.Context; +import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.os.BatteryUsageStats; @@ -41,6 +42,7 @@ import androidx.preference.PreferenceScreen; import com.android.settings.SettingsActivity; import com.android.settings.fuelgauge.BatteryDiffEntry; import com.android.settings.fuelgauge.BatteryUtils; +import com.android.settingslib.applications.ApplicationsState; import org.junit.Before; import org.junit.Test; @@ -176,6 +178,26 @@ public class AppBatteryPreferenceControllerTest { assertThat(mBatteryPreference.getSummary()).isEqualTo("60% use for past 24 hours"); } + @Test + public void displayPreference_noEntry_preferenceShouldSetEmptySummary() { + mController.mParent.setAppEntry(null); + + mController.displayPreference(mScreen); + + assertThat(mBatteryPreference.getSummary()).isEqualTo(""); + } + + @Test + public void displayPreference_appIsNotInstalled_preferenceShouldSetEmptySummary() { + final ApplicationsState.AppEntry appEntry = mock(ApplicationsState.AppEntry.class); + appEntry.info = new ApplicationInfo(); + mController.mParent.setAppEntry(appEntry); + + mController.displayPreference(mScreen); + + assertThat(mBatteryPreference.getSummary()).isEqualTo(""); + } + @Test public void isBatteryStatsAvailable_hasBatteryStatsHelperAndSipper_returnTrue() { mController.mBatteryUsageStats = mBatteryUsageStats; diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerTest.java index 472bf221c57..aa7d6bc9492 100644 --- a/tests/robotests/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerTest.java @@ -34,6 +34,7 @@ import android.os.Bundle; import androidx.loader.app.LoaderManager; import androidx.preference.Preference; +import androidx.preference.PreferenceScreen; import com.android.settings.core.BasePreferenceController; import com.android.settings.datausage.AppDataUsage; @@ -54,6 +55,8 @@ public class AppDataUsagePreferenceControllerTest { private LoaderManager mLoaderManager; @Mock private AppInfoDashboardFragment mFragment; + @Mock + private PreferenceScreen mScreen; private Context mContext; private AppDataUsagePreferenceController mController; @@ -71,7 +74,7 @@ public class AppDataUsagePreferenceControllerTest { doReturn(true).when(mController).isBandwidthControlEnabled(); assertThat(mController.getAvailabilityStatus()) - .isEqualTo(BasePreferenceController.AVAILABLE); + .isEqualTo(BasePreferenceController.AVAILABLE); } @Test @@ -79,13 +82,14 @@ public class AppDataUsagePreferenceControllerTest { doReturn(false).when(mController).isBandwidthControlEnabled(); assertThat(mController.getAvailabilityStatus()) - .isEqualTo(BasePreferenceController.CONDITIONALLY_UNAVAILABLE); + .isEqualTo(BasePreferenceController.CONDITIONALLY_UNAVAILABLE); } @Test public void onResume_notAvailable_shouldNotRestartDataLoader() { doReturn(mLoaderManager).when(mFragment).getLoaderManager(); - doReturn(BasePreferenceController.CONDITIONALLY_UNAVAILABLE).when(mController).getAvailabilityStatus(); + doReturn(BasePreferenceController.CONDITIONALLY_UNAVAILABLE).when( + mController).getAvailabilityStatus(); mController.onResume(); @@ -130,4 +134,45 @@ public class AppDataUsagePreferenceControllerTest { verify(preference).setSummary(any()); } + + @Test + public void displayPreference_noEntry_preferenceShouldNotEnable() { + mController.mAppEntry = null; + Preference preference = new Preference(mContext); + when(mScreen.findPreference(any())).thenReturn(preference); + doReturn(true).when(mController).isBandwidthControlEnabled(); + + mController.displayPreference(mScreen); + + assertThat(preference.isEnabled()).isFalse(); + } + + @Test + public void displayPreference_appIsInstalled_preferenceShouldEnable() { + final AppEntry appEntry = mock(AppEntry.class); + appEntry.info = new ApplicationInfo(); + appEntry.info.flags = ApplicationInfo.FLAG_INSTALLED; + mController.mAppEntry = appEntry; + Preference preference = new Preference(mContext); + when(mScreen.findPreference(any())).thenReturn(preference); + doReturn(true).when(mController).isBandwidthControlEnabled(); + + mController.displayPreference(mScreen); + + assertThat(preference.isEnabled()).isTrue(); + } + + @Test + public void displayPreference_appIsNotInstalled_preferenceShouldDisable() { + final AppEntry appEntry = mock(AppEntry.class); + appEntry.info = new ApplicationInfo(); + mController.mAppEntry = appEntry; + Preference preference = new Preference(mContext); + when(mScreen.findPreference(any())).thenReturn(preference); + doReturn(true).when(mController).isBandwidthControlEnabled(); + + mController.displayPreference(mScreen); + + assertThat(preference.isEnabled()).isFalse(); + } } diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/AppStoragePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/AppStoragePreferenceControllerTest.java index 065544b2f68..27e5db7a2ed 100644 --- a/tests/robotests/src/com/android/settings/applications/appinfo/AppStoragePreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/applications/appinfo/AppStoragePreferenceControllerTest.java @@ -21,7 +21,6 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -32,6 +31,7 @@ import android.os.Bundle; import androidx.loader.app.LoaderManager; import androidx.preference.Preference; +import androidx.preference.PreferenceScreen; import com.android.settings.applications.AppStorageSettings; import com.android.settingslib.applications.ApplicationsState.AppEntry; @@ -52,6 +52,8 @@ public class AppStoragePreferenceControllerTest { private LoaderManager mLoaderManager; @Mock private AppInfoDashboardFragment mFragment; + @Mock + private PreferenceScreen mScreen; private Context mContext; private AppStoragePreferenceController mController; @@ -89,10 +91,48 @@ public class AppStoragePreferenceControllerTest { } @Test - public void updateState_shouldUpdatePreferenceSummary() { + public void displayPreference_noEntry_preferenceShouldNotEnable() { + mController.mAppEntry = null; + Preference preference = new Preference(mContext); + when(mScreen.findPreference(any())).thenReturn(preference); + + mController.displayPreference(mScreen); + + assertThat(preference.isEnabled()).isFalse(); + } + + @Test + public void displayPreference_appIsInstalled_preferenceShouldEnable() { final AppEntry appEntry = mock(AppEntry.class); appEntry.info = new ApplicationInfo(); - when(mFragment.getAppEntry()).thenReturn(appEntry); + appEntry.info.flags = ApplicationInfo.FLAG_INSTALLED; + mController.mAppEntry = appEntry; + Preference preference = new Preference(mContext); + when(mScreen.findPreference(any())).thenReturn(preference); + + mController.displayPreference(mScreen); + + assertThat(preference.isEnabled()).isTrue(); + } + + @Test + public void displayPreference_appIsNotInstalled_preferenceShouldDisable() { + final AppEntry appEntry = mock(AppEntry.class); + appEntry.info = new ApplicationInfo(); + mController.mAppEntry = appEntry; + Preference preference = new Preference(mContext); + when(mScreen.findPreference(any())).thenReturn(preference); + + mController.displayPreference(mScreen); + + assertThat(preference.isEnabled()).isFalse(); + } + + @Test + public void updateState_hasAppEntry_shouldUpdatePreferenceSummary() { + final AppEntry appEntry = mock(AppEntry.class); + appEntry.info = new ApplicationInfo(); + mController.mAppEntry = appEntry; Preference preference = mock(Preference.class); mController.updateState(preference); @@ -102,12 +142,12 @@ public class AppStoragePreferenceControllerTest { @Test public void updateState_entryIsNull_shouldNotUpdatePreferenceSummary() { - when(mFragment.getAppEntry()).thenReturn(null); - Preference preference = mock(Preference.class); + mController.mAppEntry = null; + Preference preference = new Preference(mContext); mController.updateState(preference); - verify(preference, never()).setSummary(any()); + assertThat(preference.getSummary()).isEqualTo(""); } @Test diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/TimeSpentInAppPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/TimeSpentInAppPreferenceControllerTest.java index 775025616ba..0f3e7469ba3 100644 --- a/tests/robotests/src/com/android/settings/applications/appinfo/TimeSpentInAppPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/applications/appinfo/TimeSpentInAppPreferenceControllerTest.java @@ -20,7 +20,9 @@ import static android.content.Intent.EXTRA_PACKAGE_NAME; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.nullable; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -35,6 +37,7 @@ import androidx.preference.PreferenceScreen; import com.android.settings.core.BasePreferenceController; import com.android.settings.testutils.FakeFeatureFactory; +import com.android.settingslib.applications.ApplicationsState; import org.junit.Before; import org.junit.Test; @@ -125,4 +128,42 @@ public class TimeSpentInAppPreferenceControllerTest { verify(mFeatureFactory.applicationFeatureProvider).getTimeSpentInApp( nullable(String.class)); } + + @Test + public void displayPreference_noEntry_preferenceShouldNotEnable() { + mController.mAppEntry = null; + Preference preference = new Preference(mContext); + when(mScreen.findPreference(any())).thenReturn(preference); + + mController.displayPreference(mScreen); + + assertThat(preference.isEnabled()).isFalse(); + } + + @Test + public void displayPreference_appIsInstalled_preferenceShouldEnable() { + final ApplicationsState.AppEntry appEntry = mock(ApplicationsState.AppEntry.class); + appEntry.info = new ApplicationInfo(); + appEntry.info.flags = ApplicationInfo.FLAG_INSTALLED; + mController.mAppEntry = appEntry; + Preference preference = new Preference(mContext); + when(mScreen.findPreference(any())).thenReturn(preference); + + mController.displayPreference(mScreen); + + assertThat(preference.isEnabled()).isTrue(); + } + + @Test + public void displayPreference_appIsNotInstalled_preferenceShouldDisable() { + final ApplicationsState.AppEntry appEntry = mock(ApplicationsState.AppEntry.class); + appEntry.info = new ApplicationInfo(); + mController.mAppEntry = appEntry; + Preference preference = new Preference(mContext); + when(mScreen.findPreference(any())).thenReturn(preference); + + mController.displayPreference(mScreen); + + assertThat(preference.isEnabled()).isFalse(); + } }