1/*
2 * Copyright (C) 2016 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.settings.applications;
18
19import android.app.admin.DevicePolicyManager;
20import android.content.ComponentName;
21import android.content.Context;
22import android.content.Intent;
23import android.content.pm.ComponentInfo;
24import android.content.pm.IPackageManager;
25import android.content.pm.PackageManager;
26import android.content.pm.ResolveInfo;
27import android.content.pm.UserInfo;
28import android.os.RemoteException;
29import android.os.UserManager;
30import android.telecom.DefaultDialerManager;
31import android.text.TextUtils;
32import android.util.ArraySet;
33
34import com.android.internal.telephony.SmsApplication;
35import com.android.settingslib.wrapper.PackageManagerWrapper;
36
37import java.util.ArrayList;
38import java.util.List;
39import java.util.Set;
40
41public class ApplicationFeatureProviderImpl implements ApplicationFeatureProvider {
42
43    private final Context mContext;
44    private final PackageManagerWrapper mPm;
45    private final IPackageManager mPms;
46    private final DevicePolicyManager mDpm;
47    private final UserManager mUm;
48
49    public ApplicationFeatureProviderImpl(Context context, PackageManagerWrapper pm,
50            IPackageManager pms, DevicePolicyManager dpm) {
51        mContext = context.getApplicationContext();
52        mPm = pm;
53        mPms = pms;
54        mDpm = dpm;
55        mUm = UserManager.get(mContext);
56    }
57
58    @Override
59    public void calculateNumberOfPolicyInstalledApps(boolean async, NumberOfAppsCallback callback) {
60        final CurrentUserAndManagedProfilePolicyInstalledAppCounter counter =
61                new CurrentUserAndManagedProfilePolicyInstalledAppCounter(mContext, mPm, callback);
62        if (async) {
63            counter.execute();
64        } else {
65            counter.executeInForeground();
66        }
67    }
68
69    @Override
70    public void listPolicyInstalledApps(ListOfAppsCallback callback) {
71        final CurrentUserPolicyInstalledAppLister lister =
72                new CurrentUserPolicyInstalledAppLister(mPm, mUm, callback);
73        lister.execute();
74    }
75
76    @Override
77    public void calculateNumberOfAppsWithAdminGrantedPermissions(String[] permissions,
78            boolean async, NumberOfAppsCallback callback) {
79        final CurrentUserAndManagedProfileAppWithAdminGrantedPermissionsCounter counter =
80                new CurrentUserAndManagedProfileAppWithAdminGrantedPermissionsCounter(mContext,
81                        permissions, mPm, mPms, mDpm, callback);
82        if (async) {
83            counter.execute();
84        } else {
85            counter.executeInForeground();
86        }
87    }
88
89    @Override
90    public void listAppsWithAdminGrantedPermissions(String[] permissions,
91            ListOfAppsCallback callback) {
92        final CurrentUserAppWithAdminGrantedPermissionsLister lister =
93                new CurrentUserAppWithAdminGrantedPermissionsLister(permissions, mPm, mPms, mDpm,
94                        mUm, callback);
95        lister.execute();
96    }
97
98    @Override
99    public List<UserAppInfo> findPersistentPreferredActivities(int userId, Intent[] intents) {
100        final List<UserAppInfo> preferredActivities = new ArrayList<>();
101        final Set<UserAppInfo> uniqueApps = new ArraySet<>();
102        final UserInfo userInfo = mUm.getUserInfo(userId);
103        for (final Intent intent : intents) {
104            try {
105                final ResolveInfo resolveInfo =
106                        mPms.findPersistentPreferredActivity(intent, userId);
107                if (resolveInfo != null) {
108                    ComponentInfo componentInfo = null;
109                    if (resolveInfo.activityInfo != null) {
110                        componentInfo = resolveInfo.activityInfo;
111                    } else if (resolveInfo.serviceInfo != null) {
112                        componentInfo = resolveInfo.serviceInfo;
113                    } else if (resolveInfo.providerInfo != null) {
114                        componentInfo = resolveInfo.providerInfo;
115                    }
116                    if (componentInfo != null) {
117                        UserAppInfo info = new UserAppInfo(userInfo, componentInfo.applicationInfo);
118                        if (uniqueApps.add(info)) {
119                            preferredActivities.add(info);
120                        }
121                    }
122                }
123            } catch (RemoteException exception) {
124            }
125        }
126        return preferredActivities;
127    }
128
129    @Override
130    public Set<String> getKeepEnabledPackages() {
131        // Find current default phone/sms app. We should keep them enabled.
132        final Set<String> keepEnabledPackages = new ArraySet<>();
133        final String defaultDialer = DefaultDialerManager.getDefaultDialerApplication(mContext);
134        if (!TextUtils.isEmpty(defaultDialer)) {
135            keepEnabledPackages.add(defaultDialer);
136        }
137        final ComponentName defaultSms = SmsApplication.getDefaultSmsApplication(
138                mContext, true /* updateIfNeeded */);
139        if (defaultSms != null) {
140            keepEnabledPackages.add(defaultSms.getPackageName());
141        }
142        return keepEnabledPackages;
143    }
144
145    private static class CurrentUserAndManagedProfilePolicyInstalledAppCounter
146            extends InstalledAppCounter {
147        private NumberOfAppsCallback mCallback;
148
149        CurrentUserAndManagedProfilePolicyInstalledAppCounter(Context context,
150                PackageManagerWrapper packageManager, NumberOfAppsCallback callback) {
151            super(context, PackageManager.INSTALL_REASON_POLICY, packageManager);
152            mCallback = callback;
153        }
154
155        @Override
156        protected void onCountComplete(int num) {
157            mCallback.onNumberOfAppsResult(num);
158        }
159    }
160
161    private static class CurrentUserAndManagedProfileAppWithAdminGrantedPermissionsCounter
162            extends AppWithAdminGrantedPermissionsCounter {
163        private NumberOfAppsCallback mCallback;
164
165        CurrentUserAndManagedProfileAppWithAdminGrantedPermissionsCounter(Context context,
166                String[] permissions, PackageManagerWrapper packageManager,
167                IPackageManager packageManagerService,
168                DevicePolicyManager devicePolicyManager, NumberOfAppsCallback callback) {
169            super(context, permissions, packageManager, packageManagerService, devicePolicyManager);
170            mCallback = callback;
171        }
172
173        @Override
174        protected void onCountComplete(int num) {
175            mCallback.onNumberOfAppsResult(num);
176        }
177    }
178
179    private static class CurrentUserPolicyInstalledAppLister extends InstalledAppLister {
180        private ListOfAppsCallback mCallback;
181
182        CurrentUserPolicyInstalledAppLister(PackageManagerWrapper packageManager,
183                UserManager userManager, ListOfAppsCallback callback) {
184            super(packageManager, userManager);
185            mCallback = callback;
186        }
187
188        @Override
189        protected void onAppListBuilt(List<UserAppInfo> list) {
190            mCallback.onListOfAppsResult(list);
191        }
192    }
193
194    private static class CurrentUserAppWithAdminGrantedPermissionsLister extends
195            AppWithAdminGrantedPermissionsLister {
196        private ListOfAppsCallback mCallback;
197
198        CurrentUserAppWithAdminGrantedPermissionsLister(String[] permissions,
199                PackageManagerWrapper packageManager, IPackageManager packageManagerService,
200                DevicePolicyManager devicePolicyManager, UserManager userManager,
201                ListOfAppsCallback callback) {
202            super(permissions, packageManager, packageManagerService, devicePolicyManager,
203                    userManager);
204            mCallback = callback;
205        }
206
207        @Override
208        protected void onAppListBuilt(List<UserAppInfo> list) {
209            mCallback.onListOfAppsResult(list);
210        }
211    }
212
213}
214