• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.annotation.SuppressLint;
20 import android.app.ActivityManager;
21 import android.app.Application;
22 import android.content.BroadcastReceiver;
23 import android.content.ContentProviderClient;
24 import android.content.ContentResolver;
25 import android.content.Context;
26 import android.content.Intent;
27 import android.content.IntentFilter;
28 import android.content.om.OverlayManager;
29 import android.net.Uri;
30 import android.os.RemoteException;
31 import android.text.format.DateUtils;
32 import android.util.Log;
33 
34 import androidx.localbroadcastmanager.content.LocalBroadcastManager;
35 
36 import com.android.documentsui.base.Lookup;
37 import com.android.documentsui.base.UserId;
38 import com.android.documentsui.clipping.ClipStorage;
39 import com.android.documentsui.clipping.ClipStore;
40 import com.android.documentsui.clipping.DocumentClipper;
41 import com.android.documentsui.queries.SearchHistoryManager;
42 import com.android.documentsui.roots.ProvidersCache;
43 import com.android.documentsui.theme.ThemeOverlayManager;
44 
45 import com.google.common.collect.Lists;
46 
47 import java.util.List;
48 
49 public class DocumentsApplication extends Application {
50     private static final String TAG = "DocumentsApplication";
51     private static final long PROVIDER_ANR_TIMEOUT = 20 * DateUtils.SECOND_IN_MILLIS;
52 
53     private static final List<String> PACKAGE_FILTER_ACTIONS = Lists.newArrayList(
54             Intent.ACTION_PACKAGE_ADDED,
55             Intent.ACTION_PACKAGE_CHANGED,
56             Intent.ACTION_PACKAGE_REMOVED,
57             Intent.ACTION_PACKAGE_DATA_CLEARED
58     );
59 
60     private static final List<String> MANAGED_PROFILE_FILTER_ACTIONS = Lists.newArrayList(
61             Intent.ACTION_MANAGED_PROFILE_ADDED,
62             Intent.ACTION_MANAGED_PROFILE_REMOVED,
63             Intent.ACTION_MANAGED_PROFILE_UNLOCKED,
64             Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE
65     );
66 
67     private ProvidersCache mProviders;
68     private ThumbnailCache mThumbnailCache;
69     private ClipStorage mClipStore;
70     private DocumentClipper mClipper;
71     private DragAndDropManager mDragAndDropManager;
72     private UserIdManager mUserIdManager;
73     private Lookup<String, String> mFileTypeLookup;
74 
getProvidersCache(Context context)75     public static ProvidersCache getProvidersCache(Context context) {
76         return ((DocumentsApplication) context.getApplicationContext()).mProviders;
77     }
78 
getThumbnailCache(Context context)79     public static ThumbnailCache getThumbnailCache(Context context) {
80         final DocumentsApplication app = (DocumentsApplication) context.getApplicationContext();
81         return app.mThumbnailCache;
82     }
83 
acquireUnstableProviderOrThrow( ContentResolver resolver, String authority)84     public static ContentProviderClient acquireUnstableProviderOrThrow(
85             ContentResolver resolver, String authority) throws RemoteException {
86         final ContentProviderClient client = resolver.acquireUnstableContentProviderClient(
87                 authority);
88         if (client == null) {
89             throw new RemoteException("Failed to acquire provider for " + authority);
90         }
91         client.setDetectNotResponding(PROVIDER_ANR_TIMEOUT);
92         return client;
93     }
94 
getDocumentClipper(Context context)95     public static DocumentClipper getDocumentClipper(Context context) {
96         return ((DocumentsApplication) context.getApplicationContext()).mClipper;
97     }
98 
getClipStore(Context context)99     public static ClipStore getClipStore(Context context) {
100         return ((DocumentsApplication) context.getApplicationContext()).mClipStore;
101     }
102 
getUserIdManager(Context context)103     public static UserIdManager getUserIdManager(Context context) {
104         return ((DocumentsApplication) context.getApplicationContext()).mUserIdManager;
105     }
106 
getDragAndDropManager(Context context)107     public static DragAndDropManager getDragAndDropManager(Context context) {
108         return ((DocumentsApplication) context.getApplicationContext()).mDragAndDropManager;
109     }
110 
getFileTypeLookup(Context context)111     public static Lookup<String, String> getFileTypeLookup(Context context) {
112         return ((DocumentsApplication) context.getApplicationContext()).mFileTypeLookup;
113     }
114 
onApplyOverlayFinish(boolean result)115     private void onApplyOverlayFinish(boolean result) {
116         Log.d(TAG, "OverlayManager.setEnabled() result: " + result);
117     }
118 
119     @SuppressLint("NewApi") // OverlayManager.class is @hide
120     @Override
onCreate()121     public void onCreate() {
122         super.onCreate();
123 
124         final ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
125         final OverlayManager om = getSystemService(OverlayManager.class);
126         final int memoryClassBytes = am.getMemoryClass() * 1024 * 1024;
127 
128         if (om != null) {
129             new ThemeOverlayManager(om, getPackageName()).applyOverlays(this, true,
130                     this::onApplyOverlayFinish);
131         } else {
132             Log.w(TAG, "Can't obtain OverlayManager from System Service!");
133         }
134 
135         mUserIdManager = UserIdManager.create(this);
136 
137         mProviders = new ProvidersCache(this, mUserIdManager);
138         mProviders.updateAsync(/* forceRefreshAll= */ false, /* callback= */  null);
139 
140         mThumbnailCache = new ThumbnailCache(memoryClassBytes / 4);
141 
142         mClipStore = new ClipStorage(
143                 ClipStorage.prepareStorage(getCacheDir()),
144                 getSharedPreferences(ClipStorage.PREF_NAME, 0));
145         mClipper = DocumentClipper.create(this, mClipStore);
146 
147         mDragAndDropManager = DragAndDropManager.create(this, mClipper);
148 
149         mFileTypeLookup = new FileTypeMap(this);
150 
151         final IntentFilter packageFilter = new IntentFilter();
152         for (String packageAction : PACKAGE_FILTER_ACTIONS) {
153             packageFilter.addAction(packageAction);
154         }
155         packageFilter.addDataScheme("package");
156         registerReceiver(mCacheReceiver, packageFilter);
157 
158         final IntentFilter localeFilter = new IntentFilter();
159         localeFilter.addAction(Intent.ACTION_LOCALE_CHANGED);
160         registerReceiver(mCacheReceiver, localeFilter);
161 
162         final IntentFilter managedProfileFilter = new IntentFilter();
163         for (String managedProfileAction : MANAGED_PROFILE_FILTER_ACTIONS) {
164             managedProfileFilter.addAction(managedProfileAction);
165         }
166         registerReceiver(mCacheReceiver, managedProfileFilter);
167 
168         SearchHistoryManager.getInstance(getApplicationContext());
169     }
170 
171     @Override
onTrimMemory(int level)172     public void onTrimMemory(int level) {
173         super.onTrimMemory(level);
174 
175         mThumbnailCache.onTrimMemory(level);
176     }
177 
178     private BroadcastReceiver mCacheReceiver = new BroadcastReceiver() {
179         @Override
180         public void onReceive(Context context, Intent intent) {
181             final Uri data = intent.getData();
182             final String action = intent.getAction();
183             if (PACKAGE_FILTER_ACTIONS.contains(action) && data != null) {
184                 final String packageName = data.getSchemeSpecificPart();
185                 mProviders.updatePackageAsync(UserId.DEFAULT_USER, packageName);
186             } else if (MANAGED_PROFILE_FILTER_ACTIONS.contains(action)) {
187                 // After we have reloaded roots. Resend the broadcast locally so the other
188                 // components can reload properly after roots are updated.
189                 mProviders.updateAsync(/* forceRefreshAll= */ true,
190                         () -> LocalBroadcastManager.getInstance(context).sendBroadcast(intent));
191             } else {
192                 mProviders.updateAsync(/* forceRefreshAll= */ true, /* callback= */ null);
193             }
194         }
195     };
196 }
197