| /* |
| * 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.storagemanager.deletionhelper; |
| |
| import android.app.Activity; |
| 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.provider.Settings; |
| import androidx.annotation.VisibleForTesting; |
| import android.text.format.Formatter; |
| |
| import com.android.settingslib.Utils; |
| |
| import com.android.storagemanager.R; |
| |
| 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; |
| |
| private Clock mClock; |
| |
| 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; |
| } |
| |
| @VisibleForTesting(otherwise = VisibleForTesting.NONE) |
| protected void setClock(Clock clock) { |
| mClock = clock; |
| } |
| |
| @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)) |
| .setMessage(context.getString(R.string.deletion_helper_upsell_summary, |
| Formatter.formatFileSize(context, freedBytes))) |
| .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) { |
| Settings.Secure.putInt(getActivity().getContentResolver(), |
| Settings.Secure.AUTOMATIC_STORAGE_MANAGER_ENABLED, 1); |
| } 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); |
| long noThanksDelay = getNoThanksDelay(noThanksCount); |
| long nextShowTime = noThanksDelay == NEVER ? NEVER : getCurrentTime() + noThanksDelay; |
| editor.putLong(NEXT_SHOW_TIME, nextShowTime); |
| editor.apply(); |
| } |
| |
| finishActivity(); |
| } |
| |
| @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, getCurrentTime() + getDismissDelay(dismissCount)); |
| editor.apply(); |
| |
| finishActivity(); |
| } |
| |
| /** |
| * 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. |
| * @param time The current time in millis. |
| */ |
| public static boolean shouldShow(Context context, long time) { |
| boolean isEnabled = Utils.isStorageManagerEnabled(context); |
| if (isEnabled) { |
| return false; |
| } |
| |
| long nextTimeToShow = getSharedPreferences(context).getLong(NEXT_SHOW_TIME, 0); |
| if (nextTimeToShow == NEVER) { |
| return false; |
| } |
| |
| return time >= 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; |
| } |
| |
| private void finishActivity() { |
| Activity activity = getActivity(); |
| if (activity != null) { |
| activity.finish(); |
| } |
| } |
| |
| private long getCurrentTime() { |
| if (mClock == null) { |
| mClock = new Clock(); |
| } |
| |
| return mClock.currentTimeMillis(); |
| } |
| |
| /** |
| * Clock provides the current time. |
| */ |
| protected static class Clock { |
| /** |
| * Returns the current time in milliseconds. |
| */ |
| public long currentTimeMillis() { |
| return System.currentTimeMillis(); |
| } |
| } |
| } |