From 0216e9dc2e10e8622faceec7740e83b0c10797f9 Mon Sep 17 00:00:00 2001 From: Daniel Nishi Date: Mon, 16 May 2016 12:19:58 -0700 Subject: [PATCH] Add an upsell dialog to activate the storage manager. After a manual clear, the user will be prompted to turn on the storage manager, if it is turned off. The prompt will only show up after certain defined delay times and stop showing up entirely if denied enough times. Currently, the dialog does not actually turn on the storage manager because the storage manager is not yet landed. Bug: 28801159 Change-Id: I3c221786d08a7102b3b5357416ab12692d1894cf --- res/values/strings.xml | 9 ++ .../DeletionHelperFragment.java | 8 ++ .../StorageManagerUpsellDialog.java | 128 ++++++++++++++++++ .../deviceinfo/PrivateVolumeSettings.java | 18 ++- 4 files changed, 162 insertions(+), 1 deletion(-) create mode 100644 src/com/android/settings/deletionhelper/StorageManagerUpsellDialog.java diff --git a/res/values/strings.xml b/res/values/strings.xml index 07f36e1b803..6c9e64541cb 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -7611,4 +7611,13 @@ Remove photos & videos + + %1$s now free. Manage storage automatically? + + Let Storage manager automatically free up space by removing backed up content from your device? + + No thanks + + Turn on + diff --git a/src/com/android/settings/deletionhelper/DeletionHelperFragment.java b/src/com/android/settings/deletionhelper/DeletionHelperFragment.java index cc1a084e20e..8c08ce77a67 100644 --- a/src/com/android/settings/deletionhelper/DeletionHelperFragment.java +++ b/src/com/android/settings/deletionhelper/DeletionHelperFragment.java @@ -17,6 +17,7 @@ package com.android.settings.deletionhelper; import android.app.Application; +import android.content.Intent; import android.os.Bundle; import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceGroup; @@ -48,6 +49,9 @@ public class DeletionHelperFragment extends SettingsPreferenceFragment implement ApplicationsState.Callbacks, AppStateBaseBridge.Callback, Preference.OnPreferenceChangeListener, DeletionType.FreeableChangedListener, View.OnClickListener { + public static final int CLEAR_DATA_RESULT = 1; + public static final String FREED_BYTES_KEY = "freed"; + private static final String TAG = "DeletionHelperFragment"; private static final String EXTRA_HAS_BRIDGE = "hasBridge"; @@ -332,6 +336,10 @@ public class DeletionHelperFragment extends SettingsPreferenceFragment implement Log.e(TAG, "An error occurred while uninstalling packages."); } }); + Intent data = new Intent(); + data.putExtra(FREED_BYTES_KEY, getTotalFreeableSpace()); + getActivity().setResult(CLEAR_DATA_RESULT, data); + task.run(); finishFragment(); } diff --git a/src/com/android/settings/deletionhelper/StorageManagerUpsellDialog.java b/src/com/android/settings/deletionhelper/StorageManagerUpsellDialog.java new file mode 100644 index 00000000000..e72933ad006 --- /dev/null +++ b/src/com/android/settings/deletionhelper/StorageManagerUpsellDialog.java @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2016 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.deletionhelper; + +import android.app.AlertDialog; +import android.app.Dialog; +import android.app.DialogFragment; +import android.content.Context; +import android.content.DialogInterface; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.text.format.Formatter; +import com.android.settings.R; +import android.util.Log; + +import java.util.concurrent.TimeUnit; + +/** + * Fragment for activating the storage manager after a manual clear. + */ +public class StorageManagerUpsellDialog extends DialogFragment + implements DialogInterface.OnClickListener, DialogInterface.OnDismissListener { + public static final String TAG = "StorageManagerUpsellDialog"; + private static final String SHARED_PREFERENCES_NAME = "StorageManagerUpsellDialog"; + private static final String NEXT_SHOW_TIME = "next_show_time"; + private static final String DISMISSED_COUNT = "dismissed_count"; + private static final String NO_THANKS_COUNT = "no_thanks_count"; + + private static final String ARGS_FREED_BYTES = "freed_bytes"; + + private static final long NEVER = -1; + private static final long DISMISS_SHORT_DELAY = TimeUnit.DAYS.toMillis(14); + private static final long DISMISS_LONG_DELAY = TimeUnit.DAYS.toMillis(90); + private static final int DISMISS_LONG_THRESHOLD = 9; + private static final long NO_THANKS_SHORT_DELAY = TimeUnit.DAYS.toMillis(90); + private static final long NO_THANKS_LONG_DELAY = NEVER; + private static final int NO_THANKS_LONG_THRESHOLD = 3; + + public static StorageManagerUpsellDialog newInstance(long freedBytes) { + StorageManagerUpsellDialog dialog = new StorageManagerUpsellDialog(); + Bundle args = new Bundle(1); + args.putLong(ARGS_FREED_BYTES, freedBytes); + dialog.setArguments(args); + return dialog; + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final Bundle args = getArguments(); + long freedBytes = args.getLong(ARGS_FREED_BYTES); + + final Context context = getContext(); + return new AlertDialog.Builder(context) + .setTitle(context.getString(R.string.deletion_helper_upsell_title, + Formatter.formatFileSize(context, freedBytes))) + .setMessage(context.getString(R.string.deletion_helper_upsell_summary)) + .setPositiveButton(R.string.deletion_helper_upsell_activate, this) + .setNegativeButton(R.string.deletion_helper_upsell_cancel, this) + .create(); + } + + @Override + public void onClick(DialogInterface dialog, int buttonId) { + if (buttonId == DialogInterface.BUTTON_POSITIVE) { + // TODO: Activate the storage manager once the storage manager is landed. + } else { + SharedPreferences sp = getSharedPreferences(getContext()); + int noThanksCount = sp.getInt(NO_THANKS_COUNT, 0) + 1; + SharedPreferences.Editor editor = sp.edit(); + editor.putInt(NO_THANKS_COUNT, noThanksCount); + editor.putLong(NEXT_SHOW_TIME, + System.currentTimeMillis() + getNoThanksDelay(noThanksCount)); + editor.apply(); + } + } + + @Override + public void onCancel(DialogInterface dialog) { + SharedPreferences sp = getSharedPreferences(getContext()); + int dismissCount = sp.getInt(DISMISSED_COUNT, 0) + 1; + SharedPreferences.Editor editor = sp.edit(); + editor.putInt(DISMISSED_COUNT, dismissCount); + editor.putLong(NEXT_SHOW_TIME, + System.currentTimeMillis() + getDismissDelay(dismissCount)); + editor.apply(); + } + + /** + * Returns if the dialog should be shown, given the delays between when it is shown. + * @param context Context to get shared preferences for determining the next show time. + */ + public static boolean shouldShow(Context context) { + // TODO: If the Storage Manager is enabled, return false. + long nextTimeToShow = getSharedPreferences(context).getLong(NEXT_SHOW_TIME, 0); + + if (nextTimeToShow == NEVER) { + return false; + } + + return System.currentTimeMillis() > nextTimeToShow; + } + + private static SharedPreferences getSharedPreferences(Context context) { + return context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE); + } + + private static long getNoThanksDelay(int noThanksCount) { + return (noThanksCount > NO_THANKS_LONG_THRESHOLD) + ? NO_THANKS_LONG_DELAY : NO_THANKS_SHORT_DELAY; + } + + private static long getDismissDelay(int dismissCount) { + return (dismissCount > DISMISS_LONG_THRESHOLD) + ? DISMISS_LONG_DELAY : DISMISS_SHORT_DELAY; + } +} diff --git a/src/com/android/settings/deviceinfo/PrivateVolumeSettings.java b/src/com/android/settings/deviceinfo/PrivateVolumeSettings.java index d5cc27636a0..7c427bd1803 100644 --- a/src/com/android/settings/deviceinfo/PrivateVolumeSettings.java +++ b/src/com/android/settings/deviceinfo/PrivateVolumeSettings.java @@ -60,6 +60,7 @@ import com.android.settings.Utils; import com.android.settings.applications.ManageApplications; import com.android.settings.deletionhelper.DeletionHelperFragment; import com.android.settings.deletionhelper.AutomaticStorageManagerSettings; +import com.android.settings.deletionhelper.StorageManagerUpsellDialog; import com.android.settings.deviceinfo.StorageSettings.MountTask; import com.android.settingslib.deviceinfo.StorageMeasurement; import com.android.settingslib.deviceinfo.StorageMeasurement.MeasurementDetails; @@ -100,6 +101,9 @@ public class PrivateVolumeSettings extends SettingsPreferenceFragment { R.string.storage_detail_other }; + private static final int DELETION_HELPER_SETTINGS = 1; + private static final int DELETION_HELPER_CLEAR = 1; + private StorageManager mStorageManager; private UserManager mUserManager; @@ -418,7 +422,7 @@ public class PrivateVolumeSettings extends SettingsPreferenceFragment { return true; case R.id.storage_free: startFragment(this, DeletionHelperFragment.class.getCanonicalName(), - R.string.deletion_helper_title, 0, args); + R.string.deletion_helper_title, DELETION_HELPER_SETTINGS, args); return true; } return super.onOptionsItemSelected(item); @@ -507,6 +511,18 @@ public class PrivateVolumeSettings extends SettingsPreferenceFragment { return super.onPreferenceTreeClick(pref); } + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == DELETION_HELPER_SETTINGS && resultCode == DELETION_HELPER_CLEAR && + StorageManagerUpsellDialog.shouldShow(getActivity())) { + long freedBytes = data.getLongExtra(DeletionHelperFragment.FREED_BYTES_KEY, 0); + StorageManagerUpsellDialog dialog = + StorageManagerUpsellDialog.newInstance(freedBytes); + dialog.show(getFragmentManager(), StorageManagerUpsellDialog.TAG); + } + } + private final MeasurementReceiver mReceiver = new MeasurementReceiver() { @Override public void onDetailsChanged(MeasurementDetails details) {