diff --git a/res/xml/app_storage_settings.xml b/res/xml/app_storage_settings.xml index b96afbf84b6..f3f2f757eec 100644 --- a/res/xml/app_storage_settings.xml +++ b/res/xml/app_storage_settings.xml @@ -18,10 +18,8 @@ xmlns:settings="http://schemas.android.com/apk/res-auto" android:title="@string/application_info_label"> - + { @@ -102,9 +104,8 @@ public class AppStorageSettings extends AppInfoWithHeader private static final String KEY_DATA_CLEARED = "data_cleared"; // Views related to cache info - private Preference mCacheSize; - private Button mClearDataButton; - private Button mClearCacheButton; + @VisibleForTesting + ActionButtonPreference mButtonsPref; private Preference mStorageUsed; private Button mChangeStorageButton; @@ -118,7 +119,8 @@ public class AppStorageSettings extends AppInfoWithHeader private boolean mCacheCleared; private boolean mDataCleared; - private AppStorageSizesController mSizeController; + @VisibleForTesting + AppStorageSizesController mSizeController; private ClearCacheObserver mClearCacheObserver; private ClearUserDataObserver mClearDataObserver; @@ -164,9 +166,9 @@ public class AppStorageSettings extends AppInfoWithHeader .setComputingString(R.string.computing_size) .setErrorString(R.string.invalid_size_value) .build(); - - mClearDataButton = (Button) ((LayoutPreference) findPreference(KEY_HEADER_BUTTONS)) - .findViewById(R.id.left_button); + mButtonsPref = ((ActionButtonPreference) findPreference(KEY_HEADER_BUTTONS)) + .setButton1Positive(false) + .setButton2Positive(false); mStorageUsed = findPreference(KEY_STORAGE_USED); mChangeStorageButton = (Button) ((LayoutPreference) findPreference(KEY_CHANGE_STORAGE)) @@ -175,10 +177,7 @@ public class AppStorageSettings extends AppInfoWithHeader mChangeStorageButton.setOnClickListener(this); // Cache section - mCacheSize = findPreference(KEY_CACHE_SIZE); - mClearCacheButton = (Button) ((LayoutPreference) findPreference(KEY_HEADER_BUTTONS)) - .findViewById(R.id.right_button); - mClearCacheButton.setText(R.string.clear_cache_btn_text); + mButtonsPref.setButton2Text(R.string.clear_cache_btn_text); // URI permissions section mUri = (PreferenceCategory) findPreference(KEY_URI_CATEGORY); @@ -188,34 +187,40 @@ public class AppStorageSettings extends AppInfoWithHeader mClearUriButton.setOnClickListener(this); } + @VisibleForTesting + void handleClearCacheClick() { + if (mAppsControlDisallowedAdmin != null && !mAppsControlDisallowedBySystem) { + RestrictedLockUtils.sendShowAdminSupportDetailsIntent( + getActivity(), mAppsControlDisallowedAdmin); + return; + } else if (mClearCacheObserver == null) { // Lazy initialization of observer + mClearCacheObserver = new ClearCacheObserver(); + } + mMetricsFeatureProvider.action(getContext(), + MetricsEvent.ACTION_SETTINGS_CLEAR_APP_CACHE); + mPm.deleteApplicationCacheFiles(mPackageName, mClearCacheObserver); + } + + @VisibleForTesting + void handleClearDataClick() { + if (mAppsControlDisallowedAdmin != null && !mAppsControlDisallowedBySystem) { + RestrictedLockUtils.sendShowAdminSupportDetailsIntent( + getActivity(), mAppsControlDisallowedAdmin); + } else if (mAppEntry.info.manageSpaceActivityName != null) { + if (!Utils.isMonkeyRunning()) { + Intent intent = new Intent(Intent.ACTION_DEFAULT); + intent.setClassName(mAppEntry.info.packageName, + mAppEntry.info.manageSpaceActivityName); + startActivityForResult(intent, REQUEST_MANAGE_SPACE); + } + } else { + showDialogInner(DLG_CLEAR_DATA, 0); + } + } + @Override public void onClick(View v) { - if (v == mClearCacheButton) { - if (mAppsControlDisallowedAdmin != null && !mAppsControlDisallowedBySystem) { - RestrictedLockUtils.sendShowAdminSupportDetailsIntent( - getActivity(), mAppsControlDisallowedAdmin); - return; - } else if (mClearCacheObserver == null) { // Lazy initialization of observer - mClearCacheObserver = new ClearCacheObserver(); - } - mMetricsFeatureProvider.action(getContext(), - MetricsEvent.ACTION_SETTINGS_CLEAR_APP_CACHE); - mPm.deleteApplicationCacheFiles(mPackageName, mClearCacheObserver); - } else if (v == mClearDataButton) { - if (mAppsControlDisallowedAdmin != null && !mAppsControlDisallowedBySystem) { - RestrictedLockUtils.sendShowAdminSupportDetailsIntent( - getActivity(), mAppsControlDisallowedAdmin); - } else if (mAppEntry.info.manageSpaceActivityName != null) { - if (!Utils.isMonkeyRunning()) { - Intent intent = new Intent(Intent.ACTION_DEFAULT); - intent.setClassName(mAppEntry.info.packageName, - mAppEntry.info.manageSpaceActivityName); - startActivityForResult(intent, REQUEST_MANAGE_SPACE); - } - } else { - showDialogInner(DLG_CLEAR_DATA, 0); - } - } else if (v == mChangeStorageButton && mDialogBuilder != null && !isMoveInProgress()) { + if (v == mChangeStorageButton && mDialogBuilder != null && !isMoveInProgress()) { mDialogBuilder.show(); } else if (v == mClearUriButton) { if (mAppsControlDisallowedAdmin != null && !mAppsControlDisallowedBySystem) { @@ -296,20 +301,23 @@ public class AppStorageSettings extends AppInfoWithHeader if ((!appHasSpaceManagementUI && appRestrictsClearingData) || !isManageSpaceActivityAvailable) { - mClearDataButton.setText(R.string.clear_user_data_text); - mClearDataButton.setEnabled(false); + mButtonsPref + .setButton1Text(R.string.clear_user_data_text) + .setButton1Enabled(false); mCanClearData = false; } else { if (appHasSpaceManagementUI) { - mClearDataButton.setText(R.string.manage_space_text); + mButtonsPref.setButton1Text(R.string.manage_space_text); } else { - mClearDataButton.setText(R.string.clear_user_data_text); + mButtonsPref.setButton1Text(R.string.clear_user_data_text); } - mClearDataButton.setOnClickListener(this); + mButtonsPref + .setButton1Text(R.string.clear_user_data_text) + .setButton1OnClickListener(v -> handleClearDataClick()); } if (mAppsControlDisallowedBySystem) { - mClearDataButton.setEnabled(false); + mButtonsPref.setButton1Enabled(false); } } @@ -349,7 +357,7 @@ public class AppStorageSettings extends AppInfoWithHeader */ private void initiateClearUserData() { mMetricsFeatureProvider.action(getContext(), MetricsEvent.ACTION_SETTINGS_CLEAR_APP_DATA); - mClearDataButton.setEnabled(false); + mButtonsPref.setButton1Enabled(false); // Invoke uninstall or clear user data based on sysPackage String packageName = mAppEntry.info.packageName; Log.i(TAG, "Clearing user data for package : " + packageName); @@ -361,10 +369,10 @@ public class AppStorageSettings extends AppInfoWithHeader boolean res = am.clearApplicationUserData(packageName, mClearDataObserver); if (!res) { // Clearing data failed for some obscure reason. Just log error for now - Log.i(TAG, "Couldnt clear application user data for package:"+packageName); + Log.i(TAG, "Couldnt clear application user data for package:" + packageName); showDialogInner(DLG_CANNOT_CLEAR_DATA, 0); } else { - mClearDataButton.setText(R.string.recompute_size); + mButtonsPref.setButton1Text(R.string.recompute_size); } } @@ -375,12 +383,12 @@ public class AppStorageSettings extends AppInfoWithHeader private void processClearMsg(Message msg) { int result = msg.arg1; String packageName = mAppEntry.info.packageName; - mClearDataButton.setText(R.string.clear_user_data_text); + mButtonsPref.setButton1Text(R.string.clear_user_data_text); if (result == OP_SUCCESSFUL) { - Log.i(TAG, "Cleared user data for package : "+packageName); + Log.i(TAG, "Cleared user data for package : " + packageName); updateSize(); } else { - mClearDataButton.setEnabled(true); + mButtonsPref.setButton1Enabled(true); } } @@ -482,7 +490,7 @@ public class AppStorageSettings extends AppInfoWithHeader .setMessage(getActivity().getText(R.string.clear_failed_dlg_text)) .setNeutralButton(R.string.dlg_ok, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { - mClearDataButton.setEnabled(false); + mButtonsPref.setButton1Enabled(false); //force to recompute changed value setIntentAndFinish(false, false); } @@ -528,7 +536,8 @@ public class AppStorageSettings extends AppInfoWithHeader getLoaderManager().restartLoader(1, Bundle.EMPTY, this); } - private void updateUiWithSize(AppStorageStats result) { + @VisibleForTesting + void updateUiWithSize(AppStorageStats result) { if (mCacheCleared) { mSizeController.setCacheCleared(true); } @@ -539,29 +548,26 @@ public class AppStorageSettings extends AppInfoWithHeader mSizeController.updateUi(getContext()); if (result == null) { - mClearDataButton.setEnabled(false); - mClearCacheButton.setEnabled(false); + mButtonsPref.setButton1Enabled(false).setButton2Enabled(false); } else { - long codeSize = result.getCodeBytes(); long cacheSize = result.getCacheBytes(); long dataSize = result.getDataBytes() - cacheSize; if (dataSize <= 0 || !mCanClearData || mDataCleared) { - mClearDataButton.setEnabled(false); + mButtonsPref.setButton1Enabled(false); } else { - mClearDataButton.setEnabled(true); - mClearDataButton.setOnClickListener(this); + mButtonsPref.setButton1Enabled(true) + .setButton1OnClickListener(v -> handleClearDataClick()); } if (cacheSize <= 0 || mCacheCleared) { - mClearCacheButton.setEnabled(false); + mButtonsPref.setButton2Enabled(false); } else { - mClearCacheButton.setEnabled(true); - mClearCacheButton.setOnClickListener(this); + mButtonsPref.setButton2Enabled(true) + .setButton2OnClickListener(v -> handleClearCacheClick()); } } if (mAppsControlDisallowedBySystem) { - mClearCacheButton.setEnabled(false); - mClearDataButton.setEnabled(false); + mButtonsPref.setButton1Enabled(false).setButton2Enabled(false); } } @@ -599,10 +605,10 @@ public class AppStorageSettings extends AppInfoWithHeader } class ClearUserDataObserver extends IPackageDataObserver.Stub { - public void onRemoveCompleted(final String packageName, final boolean succeeded) { - final Message msg = mHandler.obtainMessage(MSG_CLEAR_USER_DATA); - msg.arg1 = succeeded ? OP_SUCCESSFUL : OP_FAILED; - mHandler.sendMessage(msg); + public void onRemoveCompleted(final String packageName, final boolean succeeded) { + final Message msg = mHandler.obtainMessage(MSG_CLEAR_USER_DATA); + msg.arg1 = succeeded ? OP_SUCCESSFUL : OP_FAILED; + mHandler.sendMessage(msg); } } } diff --git a/tests/robotests/src/com/android/settings/applications/AppStorageSettingsTest.java b/tests/robotests/src/com/android/settings/applications/AppStorageSettingsTest.java new file mode 100644 index 00000000000..1f6aea4fcd7 --- /dev/null +++ b/tests/robotests/src/com/android/settings/applications/AppStorageSettingsTest.java @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2017 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.settings.applications; + + +import static org.mockito.ArgumentMatchers.nullable; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.doNothing; +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; + +import android.content.Context; +import android.view.View; +import android.widget.Button; + +import com.android.settings.TestConfig; +import com.android.settings.testutils.SettingsRobolectricTestRunner; +import com.android.settings.widget.ActionButtonPreference; +import com.android.settings.widget.ActionButtonPreferenceTest; +import com.android.settingslib.applications.StorageStatsSource.AppStorageStats; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class AppStorageSettingsTest { + + @Mock + private AppStorageSizesController mSizesController; + private ActionButtonPreference mButtonsPref; + private AppStorageSettings mSettings; + private Button mLeftButton; + private Button mRightButton; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mLeftButton = new Button(RuntimeEnvironment.application); + mRightButton = new Button(RuntimeEnvironment.application); + mSettings = spy(new AppStorageSettings()); + mSettings.mSizeController = mSizesController; + mButtonsPref = ActionButtonPreferenceTest.createMock(); + mSettings.mButtonsPref = mButtonsPref; + + when(mButtonsPref.setButton1OnClickListener(any(View.OnClickListener.class))) + .thenAnswer(invocation -> { + final Object[] args = invocation.getArguments(); + mLeftButton.setOnClickListener((View.OnClickListener) args[0]); + return mButtonsPref; + }); + when(mButtonsPref.setButton2OnClickListener(any(View.OnClickListener.class))) + .thenAnswer(invocation -> { + final Object[] args = invocation.getArguments(); + mRightButton.setOnClickListener((View.OnClickListener) args[0]); + return mButtonsPref; + }); + } + + @Test + public void updateUiWithSize_noAppStats_shouldDisableClearButtons() { + mSettings.updateUiWithSize(null); + + verify(mSizesController).updateUi(nullable(Context.class)); + verify(mButtonsPref).setButton1Enabled(false); + verify(mButtonsPref).setButton2Enabled(false); + } + + @Test + public void updateUiWithSize_hasDataAndCache_shouldEnableClearButtons() { + final AppStorageStats stats = mock(AppStorageStats.class); + when(stats.getCacheBytes()).thenReturn(5000L); + when(stats.getDataBytes()).thenReturn(10000L); + doNothing().when(mSettings).handleClearCacheClick(); + doNothing().when(mSettings).handleClearDataClick(); + + mSettings.updateUiWithSize(stats); + verify(mButtonsPref).setButton1Enabled(true); + verify(mButtonsPref).setButton2Enabled(true); + mLeftButton.performClick(); + verify(mSettings).handleClearDataClick(); + verify(mSettings, never()).handleClearCacheClick(); + + mRightButton.performClick(); + verify(mSettings).handleClearDataClick(); + verify(mSettings).handleClearCacheClick(); + } +} +