Home | History | Annotate | Download | only in launcher3
      1 /*
      2  * Copyright (C) 2013 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.launcher3;
     18 
     19 import android.app.SearchManager;
     20 import android.content.ComponentName;
     21 import android.content.ContentResolver;
     22 import android.content.Context;
     23 import android.content.Intent;
     24 import android.content.IntentFilter;
     25 import android.content.res.Configuration;
     26 import android.content.res.Resources;
     27 import android.database.ContentObserver;
     28 import android.os.Handler;
     29 import android.util.Log;
     30 
     31 import com.android.launcher3.compat.LauncherAppsCompat;
     32 import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo;
     33 
     34 import java.lang.ref.WeakReference;
     35 import java.util.ArrayList;
     36 
     37 public class LauncherAppState implements DeviceProfile.DeviceProfileCallbacks {
     38     private static final String TAG = "LauncherAppState";
     39     private static final String SHARED_PREFERENCES_KEY = "com.android.launcher3.prefs";
     40 
     41     private static final boolean DEBUG = false;
     42 
     43     private final AppFilter mAppFilter;
     44     private final BuildInfo mBuildInfo;
     45     private LauncherModel mModel;
     46     private IconCache mIconCache;
     47     private WidgetPreviewLoader.CacheDb mWidgetPreviewCacheDb;
     48     private boolean mIsScreenLarge;
     49     private float mScreenDensity;
     50     private int mLongPressTimeout = 300;
     51     private boolean mWallpaperChangedSinceLastCheck;
     52 
     53     private static WeakReference<LauncherProvider> sLauncherProvider;
     54     private static Context sContext;
     55 
     56     private static LauncherAppState INSTANCE;
     57 
     58     private DynamicGrid mDynamicGrid;
     59 
     60     public static LauncherAppState getInstance() {
     61         if (INSTANCE == null) {
     62             INSTANCE = new LauncherAppState();
     63         }
     64         return INSTANCE;
     65     }
     66 
     67     public static LauncherAppState getInstanceNoCreate() {
     68         return INSTANCE;
     69     }
     70 
     71     public Context getContext() {
     72         return sContext;
     73     }
     74 
     75     public static void setApplicationContext(Context context) {
     76         if (sContext != null) {
     77             Log.w(Launcher.TAG, "setApplicationContext called twice! old=" + sContext + " new=" + context);
     78         }
     79         sContext = context.getApplicationContext();
     80     }
     81 
     82     private LauncherAppState() {
     83         if (sContext == null) {
     84             throw new IllegalStateException("LauncherAppState inited before app context set");
     85         }
     86 
     87         Log.v(Launcher.TAG, "LauncherAppState inited");
     88 
     89         if (sContext.getResources().getBoolean(R.bool.debug_memory_enabled)) {
     90             MemoryTracker.startTrackingMe(sContext, "L");
     91         }
     92 
     93         // set sIsScreenXLarge and mScreenDensity *before* creating icon cache
     94         mIsScreenLarge = isScreenLarge(sContext.getResources());
     95         mScreenDensity = sContext.getResources().getDisplayMetrics().density;
     96 
     97         recreateWidgetPreviewDb();
     98         mIconCache = new IconCache(sContext);
     99 
    100         mAppFilter = AppFilter.loadByName(sContext.getString(R.string.app_filter_class));
    101         mBuildInfo = BuildInfo.loadByName(sContext.getString(R.string.build_info_class));
    102         mModel = new LauncherModel(this, mIconCache, mAppFilter);
    103         final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(sContext);
    104         launcherApps.addOnAppsChangedCallback(mModel);
    105 
    106         // Register intent receivers
    107         IntentFilter filter = new IntentFilter();
    108         filter.addAction(Intent.ACTION_LOCALE_CHANGED);
    109         filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
    110         sContext.registerReceiver(mModel, filter);
    111         filter = new IntentFilter();
    112         filter.addAction(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED);
    113         sContext.registerReceiver(mModel, filter);
    114         filter = new IntentFilter();
    115         filter.addAction(SearchManager.INTENT_ACTION_SEARCHABLES_CHANGED);
    116         sContext.registerReceiver(mModel, filter);
    117 
    118         // Register for changes to the favorites
    119         ContentResolver resolver = sContext.getContentResolver();
    120         resolver.registerContentObserver(LauncherSettings.Favorites.CONTENT_URI, true,
    121                 mFavoritesObserver);
    122     }
    123 
    124     public void recreateWidgetPreviewDb() {
    125         if (mWidgetPreviewCacheDb != null) {
    126             mWidgetPreviewCacheDb.close();
    127         }
    128         mWidgetPreviewCacheDb = new WidgetPreviewLoader.CacheDb(sContext);
    129     }
    130 
    131     /**
    132      * Call from Application.onTerminate(), which is not guaranteed to ever be called.
    133      */
    134     public void onTerminate() {
    135         sContext.unregisterReceiver(mModel);
    136         final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(sContext);
    137         launcherApps.removeOnAppsChangedCallback(mModel);
    138 
    139         ContentResolver resolver = sContext.getContentResolver();
    140         resolver.unregisterContentObserver(mFavoritesObserver);
    141     }
    142 
    143     /**
    144      * Receives notifications whenever the user favorites have changed.
    145      */
    146     private final ContentObserver mFavoritesObserver = new ContentObserver(new Handler()) {
    147         @Override
    148         public void onChange(boolean selfChange) {
    149             // If the database has ever changed, then we really need to force a reload of the
    150             // workspace on the next load
    151             mModel.resetLoadedState(false, true);
    152             mModel.startLoaderFromBackground();
    153         }
    154     };
    155 
    156     LauncherModel setLauncher(Launcher launcher) {
    157         if (mModel == null) {
    158             throw new IllegalStateException("setLauncher() called before init()");
    159         }
    160         mModel.initialize(launcher);
    161         return mModel;
    162     }
    163 
    164     public IconCache getIconCache() {
    165         return mIconCache;
    166     }
    167 
    168     LauncherModel getModel() {
    169         return mModel;
    170     }
    171 
    172     boolean shouldShowAppOrWidgetProvider(ComponentName componentName) {
    173         return mAppFilter == null || mAppFilter.shouldShowApp(componentName);
    174     }
    175 
    176     WidgetPreviewLoader.CacheDb getWidgetPreviewCacheDb() {
    177         return mWidgetPreviewCacheDb;
    178     }
    179 
    180     static void setLauncherProvider(LauncherProvider provider) {
    181         sLauncherProvider = new WeakReference<LauncherProvider>(provider);
    182     }
    183 
    184     static LauncherProvider getLauncherProvider() {
    185         return sLauncherProvider.get();
    186     }
    187 
    188     public static String getSharedPreferencesKey() {
    189         return SHARED_PREFERENCES_KEY;
    190     }
    191 
    192     DeviceProfile initDynamicGrid(Context context, int minWidth, int minHeight,
    193                                   int width, int height,
    194                                   int availableWidth, int availableHeight) {
    195         if (mDynamicGrid == null) {
    196             mDynamicGrid = new DynamicGrid(context,
    197                     context.getResources(),
    198                     minWidth, minHeight, width, height,
    199                     availableWidth, availableHeight);
    200             mDynamicGrid.getDeviceProfile().addCallback(this);
    201         }
    202 
    203         // Update the icon size
    204         DeviceProfile grid = mDynamicGrid.getDeviceProfile();
    205         grid.updateFromConfiguration(context, context.getResources(), width, height,
    206                 availableWidth, availableHeight);
    207         return grid;
    208     }
    209     public DynamicGrid getDynamicGrid() {
    210         return mDynamicGrid;
    211     }
    212 
    213     public boolean isScreenLarge() {
    214         return mIsScreenLarge;
    215     }
    216 
    217     // Need a version that doesn't require an instance of LauncherAppState for the wallpaper picker
    218     public static boolean isScreenLarge(Resources res) {
    219         return res.getBoolean(R.bool.is_large_tablet);
    220     }
    221 
    222     public static boolean isScreenLandscape(Context context) {
    223         return context.getResources().getConfiguration().orientation ==
    224             Configuration.ORIENTATION_LANDSCAPE;
    225     }
    226 
    227     public float getScreenDensity() {
    228         return mScreenDensity;
    229     }
    230 
    231     public int getLongPressTimeout() {
    232         return mLongPressTimeout;
    233     }
    234 
    235     public void onWallpaperChanged() {
    236         mWallpaperChangedSinceLastCheck = true;
    237     }
    238 
    239     public boolean hasWallpaperChangedSinceLastCheck() {
    240         boolean result = mWallpaperChangedSinceLastCheck;
    241         mWallpaperChangedSinceLastCheck = false;
    242         return result;
    243     }
    244 
    245     @Override
    246     public void onAvailableSizeChanged(DeviceProfile grid) {
    247         Utilities.setIconSize(grid.iconSizePx);
    248     }
    249 
    250     public static boolean isDisableAllApps() {
    251         // Returns false on non-dogfood builds.
    252         return getInstance().mBuildInfo.isDogfoodBuild() &&
    253                 Launcher.isPropertyEnabled(Launcher.DISABLE_ALL_APPS_PROPERTY);
    254     }
    255 
    256     public static boolean isDogfoodBuild() {
    257         return getInstance().mBuildInfo.isDogfoodBuild();
    258     }
    259 
    260     public void setPackageState(ArrayList<PackageInstallInfo> installInfo) {
    261         mModel.setPackageState(installInfo);
    262     }
    263 
    264     /**
    265      * Updates the icons and label of all icons for the provided package name.
    266      */
    267     public void updatePackageBadge(String packageName) {
    268         mModel.updatePackageBadge(packageName);
    269     }
    270 }
    271