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