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
17package com.android.documentsui;
18
19import android.app.ActivityManager;
20import android.app.Application;
21import android.content.BroadcastReceiver;
22import android.content.ContentProviderClient;
23import android.content.ContentResolver;
24import android.content.Context;
25import android.content.Intent;
26import android.content.IntentFilter;
27import android.graphics.Point;
28import android.net.Uri;
29import android.os.RemoteException;
30import android.text.format.DateUtils;
31
32public class DocumentsApplication extends Application {
33    private static final long PROVIDER_ANR_TIMEOUT = 20 * DateUtils.SECOND_IN_MILLIS;
34
35    private RootsCache mRoots;
36    private Point mThumbnailsSize;
37    private ThumbnailCache mThumbnails;
38
39    public static RootsCache getRootsCache(Context context) {
40        return ((DocumentsApplication) context.getApplicationContext()).mRoots;
41    }
42
43    public static ThumbnailCache getThumbnailsCache(Context context, Point size) {
44        final DocumentsApplication app = (DocumentsApplication) context.getApplicationContext();
45        final ThumbnailCache thumbnails = app.mThumbnails;
46        if (!size.equals(app.mThumbnailsSize)) {
47            thumbnails.evictAll();
48            app.mThumbnailsSize = size;
49        }
50        return thumbnails;
51    }
52
53    public static ContentProviderClient acquireUnstableProviderOrThrow(
54            ContentResolver resolver, String authority) throws RemoteException {
55        final ContentProviderClient client = resolver.acquireUnstableContentProviderClient(
56                authority);
57        if (client == null) {
58            throw new RemoteException("Failed to acquire provider for " + authority);
59        }
60        client.setDetectNotResponding(PROVIDER_ANR_TIMEOUT);
61        return client;
62    }
63
64    @Override
65    public void onCreate() {
66        final ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
67        final int memoryClassBytes = am.getMemoryClass() * 1024 * 1024;
68
69        mRoots = new RootsCache(this);
70        mRoots.updateAsync();
71
72        mThumbnails = new ThumbnailCache(memoryClassBytes / 4);
73
74        final IntentFilter packageFilter = new IntentFilter();
75        packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
76        packageFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
77        packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
78        packageFilter.addAction(Intent.ACTION_PACKAGE_DATA_CLEARED);
79        packageFilter.addDataScheme("package");
80        registerReceiver(mCacheReceiver, packageFilter);
81
82        final IntentFilter localeFilter = new IntentFilter();
83        localeFilter.addAction(Intent.ACTION_LOCALE_CHANGED);
84        registerReceiver(mCacheReceiver, localeFilter);
85    }
86
87    @Override
88    public void onTrimMemory(int level) {
89        super.onTrimMemory(level);
90
91        if (level >= TRIM_MEMORY_MODERATE) {
92            mThumbnails.evictAll();
93        } else if (level >= TRIM_MEMORY_BACKGROUND) {
94            mThumbnails.trimToSize(mThumbnails.size() / 2);
95        }
96    }
97
98    private BroadcastReceiver mCacheReceiver = new BroadcastReceiver() {
99        @Override
100        public void onReceive(Context context, Intent intent) {
101            final Uri data = intent.getData();
102            if (data != null) {
103                final String packageName = data.getSchemeSpecificPart();
104                mRoots.updatePackageAsync(packageName);
105            } else {
106                mRoots.updateAsync();
107            }
108        }
109    };
110}
111