aboutsummaryrefslogtreecommitdiffstats
path: root/sdk/src/java/cyanogenmod/app/suggest/AppSuggestManager.java
blob: 667eaa790b5cad20984766bdd7aab500d4834ec8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/**
 * Copyright (c) 2015, The CyanogenMod Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package cyanogenmod.app.suggest;

import android.content.Context;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;

import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import cyanogenmod.app.CMContextConstants;
import cyanogenmod.app.suggest.ApplicationSuggestion;

/**
 * Provides an interface to get information about suggested apps for an intent which may include
 * applications not installed on the device. This is used by the CMResolver in order to provide
 * suggestions when an intent is fired but no application exists for the given intent.
 *
 * @hide
 */
public class AppSuggestManager {
    private static final String TAG = AppSuggestManager.class.getSimpleName();
    private static final boolean DEBUG = true;

    private static IAppSuggestManager sImpl;

    private static AppSuggestManager sInstance;

    private Context mContext;

    /**
     * Gets an instance of the AppSuggestManager.
     *
     * @param context
     *
     * @return An instance of the AppSuggestManager
     */
    public static synchronized AppSuggestManager getInstance(Context context) {
        if (sInstance != null) {
            return sInstance;
        }

        context = context.getApplicationContext() != null ?
                context.getApplicationContext() : context;

        sInstance = new AppSuggestManager(context);

        if (context.getPackageManager().hasSystemFeature(CMContextConstants.Features.APP_SUGGEST)
                && sImpl == null) {
            throw new RuntimeException("Unable to get AppSuggestManagerService. " +
                    "The service either crashed, was not started, or the interface has been" +
                    " called to early in SystemServer init");
        }

        return sInstance;
    }

    private AppSuggestManager(Context context) {
        mContext = context.getApplicationContext();
        sImpl = getService();
    }

    /** @hide */
    public static synchronized IAppSuggestManager getService() {
        if (sImpl == null) {
            IBinder b = ServiceManager.getService(CMContextConstants.CM_APP_SUGGEST_SERVICE);
            if (b != null) {
                sImpl = IAppSuggestManager.Stub.asInterface(b);
            } else {
                Log.e(TAG, "Unable to find implementation for app suggest service");
            }
        }

        return sImpl;
    }

    /**
     * Checks to see if an intent is handled by the App Suggestions Service. This should be
     * implemented in such a way that it is safe to call inline on the UI Thread.
     *
     * @param intent The intent
     * @return true if the App Suggestions Service has suggestions for this intent, false otherwise
     */
    public boolean handles(Intent intent) {
        IAppSuggestManager mgr = getService();
        if (mgr == null) return false;
        try {
            return mgr.handles(intent);
        } catch (RemoteException e) {
            return false;
        }
    }

    /**
     *
     * Gets a list of the suggestions for the given intent.
     *
     * @param intent The intent
     * @return A list of application suggestions or an empty list if none.
     */
    public List<ApplicationSuggestion> getSuggestions(Intent intent) {
        IAppSuggestManager mgr = getService();
        if (mgr == null) return new ArrayList<>(0);
        try {
            return mgr.getSuggestions(intent);
        } catch (RemoteException e) {
            return new ArrayList<>(0);
        }
    }

    /**
     * Loads the icon for the given suggestion.
     *
     * @param suggestion The suggestion to load the icon for
     *
     * @return A {@link Drawable} or null if one cannot be found
     */
    public Drawable loadIcon(ApplicationSuggestion suggestion) {
        try {
            InputStream is = mContext.getContentResolver()
                    .openInputStream(suggestion.getThumbailUri());
            return Drawable.createFromStream(is, null);
        } catch (FileNotFoundException e) {
            return null;
        }
    }
}