/*
** DroidPlugin Project
**
** Copyright(c) 2015 Andy Zhang <zhangyong232@gmail.com>
**
** This file is part of DroidPlugin.
**
** DroidPlugin is free software: you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License as published by the Free Software Foundation, either
** version 3 of the License, or (at your option) any later version.
**
** DroidPlugin is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
** Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public
** License along with DroidPlugin. If not, see <http://www.gnu.org/licenses/lgpl.txt>
**
**/
package com.morgoo.droidplugin.am;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ComponentInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ProviderInfo;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.text.TextUtils;
import com.morgoo.droidplugin.stub.ActivityStub;
import com.morgoo.droidplugin.stub.ContentProviderStub;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Created by Andy Zhang(zhangyong232@gmail.com) on 2015/3/10.
*/
class StaticProcessList {
private static final String CATEGORY_ACTIVITY_PROXY_STUB = "com.morgoo.droidplugin.category.PROXY_STUB";
//key=processName value=ProcessItem
private Map<String, ProcessItem> items = new HashMap<String, ProcessItem>(10);
private List<String> mOtherProcessNames = new ArrayList<>();
/**
* 我们预注册的进程item
* <p/>
* Created by Andy Zhang(zhangyong232@gmail.com) on 2015/3/10.
*/
private class ProcessItem {
private String name;
//key=ActivityInfo.name,value=ActivityInfo
private Map<String, ActivityInfo> activityInfos = new HashMap<String, ActivityInfo>(4);
//key=ServiceInfo.name,value=ServiceInfo
private Map<String, ServiceInfo> serviceInfos = new HashMap<String, ServiceInfo>(1);
//key=ProviderInfo.authority,value=ProviderInfo
private Map<String, ProviderInfo> providerInfos = new HashMap<String, ProviderInfo>(1);
private void addActivityInfo(ActivityInfo info) {
if (!activityInfos.containsKey(info.name)) {
activityInfos.put(info.name, info);
}
}
private void addServiceInfo(ServiceInfo info) {
if (!serviceInfos.containsKey(info.name)) {
serviceInfos.put(info.name, info);
}
}
private void addProviderInfo(ProviderInfo info) {
if (!providerInfos.containsKey(info.authority)) {
providerInfos.put(info.authority, info);
}
}
}
void onCreate(Context mHostContext) throws NameNotFoundException {
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(CATEGORY_ACTIVITY_PROXY_STUB);
intent.setPackage(mHostContext.getPackageName());
PackageManager pm = mHostContext.getPackageManager();
List<ResolveInfo> activities = pm.queryIntentActivities(intent, PackageManager.GET_META_DATA);
for (ResolveInfo activity : activities) {
addActivityInfo(activity.activityInfo);
}
List<ResolveInfo> services = pm.queryIntentServices(intent, 0);
for (ResolveInfo service : services) {
addServiceInfo(service.serviceInfo);
}
PackageInfo packageInfo = pm.getPackageInfo(mHostContext.getPackageName(), PackageManager.GET_PROVIDERS);
if (packageInfo.providers != null && packageInfo.providers.length > 0) {
for (ProviderInfo providerInfo : packageInfo.providers) {
if (providerInfo.name != null && providerInfo.name.startsWith(ContentProviderStub.class.getName())) {
addProviderInfo(providerInfo);
}
}
}
mOtherProcessNames.clear();
PackageInfo packageInfo1 = pm.getPackageInfo(mHostContext.getPackageName(), PackageManager.GET_ACTIVITIES
| PackageManager.GET_RECEIVERS
| PackageManager.GET_PROVIDERS
| PackageManager.GET_SERVICES);
if (packageInfo1.activities != null) {
for (ActivityInfo info : packageInfo1.activities) {
if (!mOtherProcessNames.contains(info.processName) && !items.containsKey(info.processName)) {
mOtherProcessNames.add(info.processName);
}
}
}
if (packageInfo1.receivers != null) {
for (ActivityInfo info : packageInfo1.receivers) {
if (!mOtherProcessNames.contains(info.processName) && !items.containsKey(info.processName)) {
mOtherProcessNames.add(info.processName);
}
}
}
if (packageInfo1.providers != null) {
for (ProviderInfo info : packageInfo1.providers) {
if (!mOtherProcessNames.contains(info.processName) && !items.containsKey(info.processName)) {
mOtherProcessNames.add(info.processName);
}
}
}
if (packageInfo1.services != null) {
for (ServiceInfo info : packageInfo1.services) {
if (!mOtherProcessNames.contains(info.processName) && !items.containsKey(info.processName)) {
mOtherProcessNames.add(info.processName);
}
}
}
}
public List<String> getOtherProcessNames() {
return mOtherProcessNames;
}
private void addActivityInfo(ActivityInfo info) {
if (TextUtils.isEmpty(info.processName)) {
info.processName = info.packageName;
}
ProcessItem item = items.get(info.processName);
if (item == null) {
item = new ProcessItem();
item.name = info.processName;
items.put(info.processName, item);
}
item.addActivityInfo(info);
}
ActivityInfo findActivityInfoForName(String processName, String activityName) {
ProcessItem item = items.get(processName);
if (item != null && item.activityInfos != null) {
return item.activityInfos.get(activityName);
}
return null;
}
ActivityInfo findActivityInfoForLaunchMode(String processName, int launchMode) {
ProcessItem item = items.get(processName);
if (item != null && item.activityInfos != null) {
for (ActivityInfo info : item.activityInfos.values()) {
if (info.launchMode == launchMode) {
return info;
}
}
}
return null;
}
private void addServiceInfo(ServiceInfo info) {
if (TextUtils.isEmpty(info.processName)) {
info.processName = info.packageName;
}
ProcessItem item = items.get(info.processName);
if (item == null) {
item = new ProcessItem();
item.name = info.processName;
items.put(info.processName, item);
}
item.addServiceInfo(info);
}
ServiceInfo findServiceInfoForName(String processName, String serviceInfoName) {
ProcessItem item = items.get(processName);
if (item != null && item.serviceInfos != null) {
return item.serviceInfos.get(serviceInfoName);
}
return null;
}
private void addProviderInfo(ProviderInfo info) {
if (TextUtils.isEmpty(info.processName)) {
info.processName = info.packageName;
}
ProcessItem item = items.get(info.processName);
if (item == null) {
item = new ProcessItem();
item.name = info.processName;
items.put(info.processName, item);
}
item.addProviderInfo(info);
}
ProviderInfo findProviderInfoForAuthority(String processName, String authority) {
ProcessItem item = items.get(processName);
if (item != null && item.providerInfos != null) {
return item.providerInfos.get(authority);
}
return null;
}
List<String> getProcessNames() {
return new ArrayList<String>(items.keySet());
}
List<ActivityInfo> getActivityInfoForProcessName(String processName) {
ProcessItem item = items.get(processName);
ArrayList<ActivityInfo> activityInfos = new ArrayList<ActivityInfo>(item.activityInfos.values());
Collections.sort(activityInfos, sComponentInfoComparator);
return activityInfos;
}
private static final Comparator<ComponentInfo> sComponentInfoComparator = new Comparator<ComponentInfo>() {
@Override
public int compare(ComponentInfo lhs, ComponentInfo rhs) {
return Collator.getInstance().compare(lhs.name, rhs.name);
}
};
List<ActivityInfo> getActivityInfoForProcessName(String processName, boolean dialogStyle) {
ProcessItem item = items.get(processName);
Collection<ActivityInfo> values = item.activityInfos.values();
ArrayList<ActivityInfo> activityInfos = new ArrayList<ActivityInfo>();
for (ActivityInfo info : values) {
if (dialogStyle) {
if (info.name.startsWith(ActivityStub.Dialog.class.getName())) {
activityInfos.add(info);
}
} else {
if (!info.name.startsWith(ActivityStub.Dialog.class.getName())) {
activityInfos.add(info);
}
}
}
Collections.sort(activityInfos, sComponentInfoComparator);
return activityInfos;
}
List<ServiceInfo> getServiceInfoForProcessName(String processName) {
ProcessItem item = items.get(processName);
ArrayList<ServiceInfo> serviceInfos = new ArrayList<ServiceInfo>(item.serviceInfos.values());
Collections.sort(serviceInfos, sComponentInfoComparator);
return serviceInfos;
}
List<ProviderInfo> getProviderInfoForProcessName(String processName) {
ProcessItem item = items.get(processName);
ArrayList<ProviderInfo> providerInfos = new ArrayList<ProviderInfo>(item.providerInfos.values());
Collections.sort(providerInfos, sComponentInfoComparator);
return providerInfos;
}
void clear() {
items.clear();
}
}