Home | History | Annotate | Download | only in storage
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.settings.deviceinfo.storage;
     18 
     19 import android.content.Context;
     20 import android.content.SharedPreferences;
     21 import android.provider.Settings;
     22 import android.support.annotation.VisibleForTesting;
     23 import android.util.SparseArray;
     24 
     25 import com.android.settingslib.applications.StorageStatsSource;
     26 import com.android.settingslib.deviceinfo.PrivateStorageInfo;
     27 
     28 import java.util.concurrent.TimeUnit;
     29 
     30 public class CachedStorageValuesHelper {
     31 
     32     @VisibleForTesting public static final String SHARED_PREFERENCES_NAME = "CachedStorageValues";
     33     public static final String TIMESTAMP_KEY = "last_query_timestamp";
     34     public static final String FREE_BYTES_KEY = "free_bytes";
     35     public static final String TOTAL_BYTES_KEY = "total_bytes";
     36     public static final String GAME_APPS_SIZE_KEY = "game_apps_size";
     37     public static final String MUSIC_APPS_SIZE_KEY = "music_apps_size";
     38     public static final String VIDEO_APPS_SIZE_KEY = "video_apps_size";
     39     public static final String PHOTO_APPS_SIZE_KEY = "photo_apps_size";
     40     public static final String OTHER_APPS_SIZE_KEY = "other_apps_size";
     41     public static final String CACHE_APPS_SIZE_KEY = "cache_apps_size";
     42     public static final String EXTERNAL_TOTAL_BYTES = "external_total_bytes";
     43     public static final String EXTERNAL_AUDIO_BYTES = "external_audio_bytes";
     44     public static final String EXTERNAL_VIDEO_BYTES = "external_video_bytes";
     45     public static final String EXTERNAL_IMAGE_BYTES = "external_image_bytes";
     46     public static final String EXTERNAL_APP_BYTES = "external_apps_bytes";
     47     public static final String USER_ID_KEY = "user_id";
     48     private final Long mClobberThreshold;
     49     private final SharedPreferences mSharedPreferences;
     50     private final int mUserId;
     51     // This clock is used to provide the time. By default, it uses the system clock, but can be
     52     // replaced for test purposes.
     53     protected Clock mClock;
     54 
     55     public CachedStorageValuesHelper(Context context, int userId) {
     56         mSharedPreferences =
     57                 context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
     58         mClock = new Clock();
     59         mUserId = userId;
     60         mClobberThreshold =
     61                 Settings.Global.getLong(
     62                         context.getContentResolver(),
     63                         Settings.Global.STORAGE_SETTINGS_CLOBBER_THRESHOLD,
     64                         TimeUnit.MINUTES.toMillis(5));
     65     }
     66 
     67     public PrivateStorageInfo getCachedPrivateStorageInfo() {
     68         if (!isDataValid()) {
     69             return null;
     70         }
     71         final long freeBytes = mSharedPreferences.getLong(FREE_BYTES_KEY, -1);
     72         final long totalBytes = mSharedPreferences.getLong(TOTAL_BYTES_KEY, -1);
     73         if (freeBytes < 0 || totalBytes < 0) {
     74             return null;
     75         }
     76 
     77         return new PrivateStorageInfo(freeBytes, totalBytes);
     78     }
     79 
     80     public SparseArray<StorageAsyncLoader.AppsStorageResult> getCachedAppsStorageResult() {
     81         if (!isDataValid()) {
     82             return null;
     83         }
     84         final long gamesSize = mSharedPreferences.getLong(GAME_APPS_SIZE_KEY, -1);
     85         final long musicAppsSize = mSharedPreferences.getLong(MUSIC_APPS_SIZE_KEY, -1);
     86         final long videoAppsSize = mSharedPreferences.getLong(VIDEO_APPS_SIZE_KEY, -1);
     87         final long photoAppSize = mSharedPreferences.getLong(PHOTO_APPS_SIZE_KEY, -1);
     88         final long otherAppsSize = mSharedPreferences.getLong(OTHER_APPS_SIZE_KEY, -1);
     89         final long cacheSize = mSharedPreferences.getLong(CACHE_APPS_SIZE_KEY, -1);
     90         if (gamesSize < 0
     91                 || musicAppsSize < 0
     92                 || videoAppsSize < 0
     93                 || photoAppSize < 0
     94                 || otherAppsSize < 0
     95                 || cacheSize < 0) {
     96             return null;
     97         }
     98 
     99         final long externalTotalBytes = mSharedPreferences.getLong(EXTERNAL_TOTAL_BYTES, -1);
    100         final long externalAudioBytes = mSharedPreferences.getLong(EXTERNAL_AUDIO_BYTES, -1);
    101         final long externalVideoBytes = mSharedPreferences.getLong(EXTERNAL_VIDEO_BYTES, -1);
    102         final long externalImageBytes = mSharedPreferences.getLong(EXTERNAL_IMAGE_BYTES, -1);
    103         final long externalAppBytes = mSharedPreferences.getLong(EXTERNAL_APP_BYTES, -1);
    104         if (externalTotalBytes < 0
    105                 || externalAudioBytes < 0
    106                 || externalVideoBytes < 0
    107                 || externalImageBytes < 0
    108                 || externalAppBytes < 0) {
    109             return null;
    110         }
    111 
    112         final StorageStatsSource.ExternalStorageStats externalStats =
    113                 new StorageStatsSource.ExternalStorageStats(
    114                         externalTotalBytes,
    115                         externalAudioBytes,
    116                         externalVideoBytes,
    117                         externalImageBytes,
    118                         externalAppBytes);
    119         final StorageAsyncLoader.AppsStorageResult result =
    120                 new StorageAsyncLoader.AppsStorageResult();
    121         result.gamesSize = gamesSize;
    122         result.musicAppsSize = musicAppsSize;
    123         result.videoAppsSize = videoAppsSize;
    124         result.photosAppsSize = photoAppSize;
    125         result.otherAppsSize = otherAppsSize;
    126         result.cacheSize = cacheSize;
    127         result.externalStats = externalStats;
    128         final SparseArray<StorageAsyncLoader.AppsStorageResult> resultArray = new SparseArray<>();
    129         resultArray.append(mUserId, result);
    130         return resultArray;
    131     }
    132 
    133     public void cacheResult(
    134             PrivateStorageInfo storageInfo, StorageAsyncLoader.AppsStorageResult result) {
    135         mSharedPreferences
    136                 .edit()
    137                 .putLong(FREE_BYTES_KEY, storageInfo.freeBytes)
    138                 .putLong(TOTAL_BYTES_KEY, storageInfo.totalBytes)
    139                 .putLong(GAME_APPS_SIZE_KEY, result.gamesSize)
    140                 .putLong(MUSIC_APPS_SIZE_KEY, result.musicAppsSize)
    141                 .putLong(VIDEO_APPS_SIZE_KEY, result.videoAppsSize)
    142                 .putLong(PHOTO_APPS_SIZE_KEY, result.photosAppsSize)
    143                 .putLong(OTHER_APPS_SIZE_KEY, result.otherAppsSize)
    144                 .putLong(CACHE_APPS_SIZE_KEY, result.cacheSize)
    145                 .putLong(EXTERNAL_TOTAL_BYTES, result.externalStats.totalBytes)
    146                 .putLong(EXTERNAL_AUDIO_BYTES, result.externalStats.audioBytes)
    147                 .putLong(EXTERNAL_VIDEO_BYTES, result.externalStats.videoBytes)
    148                 .putLong(EXTERNAL_IMAGE_BYTES, result.externalStats.imageBytes)
    149                 .putLong(EXTERNAL_APP_BYTES, result.externalStats.appBytes)
    150                 .putInt(USER_ID_KEY, mUserId)
    151                 .putLong(TIMESTAMP_KEY, mClock.getCurrentTime())
    152                 .apply();
    153     }
    154 
    155     private boolean isDataValid() {
    156         final int cachedUserId = mSharedPreferences.getInt(USER_ID_KEY, -1);
    157         if (cachedUserId != mUserId) {
    158             return false;
    159         }
    160 
    161         final long lastQueryTime = mSharedPreferences.getLong(TIMESTAMP_KEY, Long.MAX_VALUE);
    162         final long currentTime = mClock.getCurrentTime();
    163         return currentTime - lastQueryTime < mClobberThreshold;
    164     }
    165 
    166     /** Clock provides the current time. */
    167     static class Clock {
    168         public long getCurrentTime() {
    169             return System.currentTimeMillis();
    170         }
    171     }
    172 }
    173