14eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey/*
24eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey * Copyright (C) 2013 The Android Open Source Project
34eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey *
44eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License");
54eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey * you may not use this file except in compliance with the License.
64eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey * You may obtain a copy of the License at
74eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey *
84eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey *      http://www.apache.org/licenses/LICENSE-2.0
94eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey *
104eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey * Unless required by applicable law or agreed to in writing, software
114eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS,
124eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey * See the License for the specific language governing permissions and
144eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey * limitations under the License.
154eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey */
164eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey
174eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkeypackage com.android.documentsui;
184eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey
194eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkeyimport android.app.ActivityManager;
204eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkeyimport android.app.Application;
214eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkeyimport android.content.BroadcastReceiver;
227aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkeyimport android.content.ContentProviderClient;
237aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkeyimport android.content.ContentResolver;
244eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkeyimport android.content.Context;
254eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkeyimport android.content.Intent;
264eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkeyimport android.content.IntentFilter;
274eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkeyimport android.graphics.Point;
28a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkeyimport android.net.Uri;
297aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkeyimport android.os.RemoteException;
307aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkeyimport android.text.format.DateUtils;
314eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey
324eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkeypublic class DocumentsApplication extends Application {
337aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey    private static final long PROVIDER_ANR_TIMEOUT = 20 * DateUtils.SECOND_IN_MILLIS;
347aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey
354eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey    private RootsCache mRoots;
364eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey    private Point mThumbnailsSize;
374eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey    private ThumbnailCache mThumbnails;
384eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey
394eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey    public static RootsCache getRootsCache(Context context) {
404eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey        return ((DocumentsApplication) context.getApplicationContext()).mRoots;
414eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey    }
424eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey
434eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey    public static ThumbnailCache getThumbnailsCache(Context context, Point size) {
444eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey        final DocumentsApplication app = (DocumentsApplication) context.getApplicationContext();
454eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey        final ThumbnailCache thumbnails = app.mThumbnails;
464eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey        if (!size.equals(app.mThumbnailsSize)) {
474eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey            thumbnails.evictAll();
484eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey            app.mThumbnailsSize = size;
494eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey        }
504eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey        return thumbnails;
514eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey    }
524eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey
537aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey    public static ContentProviderClient acquireUnstableProviderOrThrow(
547aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey            ContentResolver resolver, String authority) throws RemoteException {
557aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey        final ContentProviderClient client = resolver.acquireUnstableContentProviderClient(
567aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey                authority);
577aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey        if (client == null) {
587aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey            throw new RemoteException("Failed to acquire provider for " + authority);
597aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey        }
607aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey        client.setDetectNotResponding(PROVIDER_ANR_TIMEOUT);
617aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey        return client;
627aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey    }
637aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey
644eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey    @Override
654eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey    public void onCreate() {
664eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey        final ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
674eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey        final int memoryClassBytes = am.getMemoryClass() * 1024 * 1024;
684eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey
694eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey        mRoots = new RootsCache(this);
70a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        mRoots.updateAsync();
71a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey
724eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey        mThumbnails = new ThumbnailCache(memoryClassBytes / 4);
734eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey
744eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey        final IntentFilter packageFilter = new IntentFilter();
754eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey        packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
764eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey        packageFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
774eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey        packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
7846de7b50243d3896fe97d1ee7a00258085cea1caJeff Sharkey        packageFilter.addAction(Intent.ACTION_PACKAGE_DATA_CLEARED);
794eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey        packageFilter.addDataScheme("package");
804ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey        registerReceiver(mCacheReceiver, packageFilter);
814ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey
824ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey        final IntentFilter localeFilter = new IntentFilter();
834ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey        localeFilter.addAction(Intent.ACTION_LOCALE_CHANGED);
844ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey        registerReceiver(mCacheReceiver, localeFilter);
854eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey    }
864eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey
874eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey    @Override
884eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey    public void onTrimMemory(int level) {
894eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey        super.onTrimMemory(level);
904eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey
914eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey        if (level >= TRIM_MEMORY_MODERATE) {
924eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey            mThumbnails.evictAll();
934eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey        } else if (level >= TRIM_MEMORY_BACKGROUND) {
944eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey            mThumbnails.trimToSize(mThumbnails.size() / 2);
954eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey        }
964eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey    }
974eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey
984ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey    private BroadcastReceiver mCacheReceiver = new BroadcastReceiver() {
994eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey        @Override
1004eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey        public void onReceive(Context context, Intent intent) {
101a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            final Uri data = intent.getData();
102a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            if (data != null) {
103a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey                final String packageName = data.getSchemeSpecificPart();
104a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey                mRoots.updatePackageAsync(packageName);
105a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            } else {
106a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey                mRoots.updateAsync();
107a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            }
1084eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey        }
1094eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey    };
1104eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey}
111