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.documentsui;
18 
19 import android.app.ActivityManager;
20 import android.app.Application;
21 import android.content.BroadcastReceiver;
22 import android.content.ContentProviderClient;
23 import android.content.ContentResolver;
24 import android.content.Context;
25 import android.content.Intent;
26 import android.content.IntentFilter;
27 import android.content.om.OverlayManager;
28 import android.net.Uri;
29 import android.os.RemoteException;
30 import android.text.format.DateUtils;
31 import android.util.Log;
32 
33 import com.android.documentsui.base.Lookup;
34 import com.android.documentsui.clipping.ClipStorage;
35 import com.android.documentsui.clipping.ClipStore;
36 import com.android.documentsui.clipping.DocumentClipper;
37 import com.android.documentsui.prefs.ScopedAccessLocalPreferences;
38 import com.android.documentsui.queries.SearchHistoryManager;
39 import com.android.documentsui.roots.ProvidersCache;
40 import com.android.documentsui.theme.ThemeOverlayManager;
41 
42 public class DocumentsApplication extends Application {
43     private static final String TAG = "DocumentsApplication";
44     private static final long PROVIDER_ANR_TIMEOUT = 20 * DateUtils.SECOND_IN_MILLIS;
45 
46     private ProvidersCache mProviders;
47     private ThumbnailCache mThumbnailCache;
48     private ClipStorage mClipStore;
49     private DocumentClipper mClipper;
50     private DragAndDropManager mDragAndDropManager;
51     private Lookup<String, String> mFileTypeLookup;
52 
getProvidersCache(Context context)53     public static ProvidersCache getProvidersCache(Context context) {
54         return ((DocumentsApplication) context.getApplicationContext()).mProviders;
55     }
56 
getThumbnailCache(Context context)57     public static ThumbnailCache getThumbnailCache(Context context) {
58         final DocumentsApplication app = (DocumentsApplication) context.getApplicationContext();
59         return app.mThumbnailCache;
60     }
61 
acquireUnstableProviderOrThrow( ContentResolver resolver, String authority)62     public static ContentProviderClient acquireUnstableProviderOrThrow(
63             ContentResolver resolver, String authority) throws RemoteException {
64         final ContentProviderClient client = resolver.acquireUnstableContentProviderClient(
65                 authority);
66         if (client == null) {
67             throw new RemoteException("Failed to acquire provider for " + authority);
68         }
69         client.setDetectNotResponding(PROVIDER_ANR_TIMEOUT);
70         return client;
71     }
72 
getDocumentClipper(Context context)73     public static DocumentClipper getDocumentClipper(Context context) {
74         return ((DocumentsApplication) context.getApplicationContext()).mClipper;
75     }
76 
getClipStore(Context context)77     public static ClipStore getClipStore(Context context) {
78         return ((DocumentsApplication) context.getApplicationContext()).mClipStore;
79     }
80 
getDragAndDropManager(Context context)81     public static DragAndDropManager getDragAndDropManager(Context context) {
82         return ((DocumentsApplication) context.getApplicationContext()).mDragAndDropManager;
83     }
84 
getFileTypeLookup(Context context)85     public static Lookup<String, String> getFileTypeLookup(Context context) {
86         return ((DocumentsApplication) context.getApplicationContext()).mFileTypeLookup;
87     }
88 
onApplyOverlayFinish(boolean result)89     private void onApplyOverlayFinish(boolean result) {
90         Log.d(TAG, "OverlayManager.setEnabled() result: " + result);
91     }
92 
93     @Override
onCreate()94     public void onCreate() {
95         super.onCreate();
96 
97         final ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
98         final OverlayManager om = getSystemService(OverlayManager.class);
99         final int memoryClassBytes = am.getMemoryClass() * 1024 * 1024;
100 
101         if (om != null) {
102             new ThemeOverlayManager(om, getPackageName()).applyOverlays(this, true,
103                     this::onApplyOverlayFinish);
104         } else {
105             Log.w(TAG, "Can't obtain OverlayManager from System Service!");
106         }
107 
108         mProviders = new ProvidersCache(this);
109         mProviders.updateAsync(false);
110 
111         mThumbnailCache = new ThumbnailCache(memoryClassBytes / 4);
112 
113         mClipStore = new ClipStorage(
114                 ClipStorage.prepareStorage(getCacheDir()),
115                 getSharedPreferences(ClipStorage.PREF_NAME, 0));
116         mClipper = DocumentClipper.create(this, mClipStore);
117 
118         mDragAndDropManager = DragAndDropManager.create(this, mClipper);
119 
120         mFileTypeLookup = new FileTypeMap(this);
121 
122         final IntentFilter packageFilter = new IntentFilter();
123         packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
124         packageFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
125         packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
126         packageFilter.addAction(Intent.ACTION_PACKAGE_DATA_CLEARED);
127         packageFilter.addDataScheme("package");
128         registerReceiver(mCacheReceiver, packageFilter);
129 
130         final IntentFilter localeFilter = new IntentFilter();
131         localeFilter.addAction(Intent.ACTION_LOCALE_CHANGED);
132         registerReceiver(mCacheReceiver, localeFilter);
133         ScopedAccessLocalPreferences.clearScopedAccessPreferences(this);
134 
135         SearchHistoryManager.getInstance(getApplicationContext());
136     }
137 
138     @Override
onTrimMemory(int level)139     public void onTrimMemory(int level) {
140         super.onTrimMemory(level);
141 
142         mThumbnailCache.onTrimMemory(level);
143     }
144 
145     private BroadcastReceiver mCacheReceiver = new BroadcastReceiver() {
146         @Override
147         public void onReceive(Context context, Intent intent) {
148             final Uri data = intent.getData();
149             if (data != null) {
150                 final String packageName = data.getSchemeSpecificPart();
151                 mProviders.updatePackageAsync(packageName);
152             } else {
153                 mProviders.updateAsync(true);
154             }
155         }
156     };
157 }
158