/* (C) 2012 Pragmatic Software
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/
*/
package com.googlecode.networklog;
import android.util.Log;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.Filter;
import android.widget.Filterable;
import android.view.View;
import android.view.ViewGroup;
import android.content.Context;
import android.content.Intent;
import android.view.LayoutInflater;
import android.graphics.drawable.Drawable;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Toast;
import android.util.TypedValue;
import android.view.MenuItem;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.MenuInflater;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.net.Uri;
/* newer API 11 clipboard unsupported on older APIs
import android.content.ClipboardManager;
import android.content.ClipData;
*/
/* use older clipboard API to support older devices */
import android.text.ClipboardManager;
import android.support.v4.app.Fragment;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
public class LogFragment extends Fragment {
// bound to adapter
protected LinkedList<ListItem> listData;
// buffers incoming log entries
protected LinkedList<ListItem> listDataBuffer;
// holds all entries, used for filtering
protected LinkedList<ListItem> listDataUnfiltered;
private CustomAdapter adapter;
private ListViewUpdater updater;
private NetworkLog parent = null;
public long maxLogEntries;
private boolean doNotRefresh = false;
public boolean needsRefresh = false;
protected class ListItem {
protected ApplicationsTracker.AppEntry app;
protected String in;
protected String out;
protected String proto;
protected String srcAddr;
protected int srcPort;
protected String dstAddr;
protected int dstPort;
protected int len;
protected long timestamp;
ListItem(ApplicationsTracker.AppEntry app) {
this.app = app;
}
@Override
public String toString() {
return app.name;
}
}
public void clear() {
synchronized(listData) {
synchronized(listDataBuffer) {
synchronized(listDataUnfiltered) {
listData.clear();
listDataBuffer.clear();
listDataUnfiltered.clear();
refreshAdapter();
}
}
}
}
public void setDoNotRefresh(boolean value) {
doNotRefresh = value;
}
public void refreshAdapter() {
if(doNotRefresh) {
return;
}
adapter.notifyDataSetChanged();
if(MyLog.enabled && MyLog.level >= 5) {
MyLog.d(5, "Refreshed LogFragment adapter");
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
setUserVisibleHint(true);
}
public void setParent(NetworkLog parent) {
this.parent = parent;
}
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (this.isVisible() && !isVisibleToUser) {
if(parent != null) {
parent.invalidateOptionsMenu();
}
}
}
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setRetainInstance(true);
listData = new LinkedList<ListItem>();
listDataBuffer = new LinkedList<ListItem>();
listDataUnfiltered = new LinkedList<ListItem>();
adapter = new CustomAdapter(getActivity().getApplicationContext(), R.layout.logitem, listData);
if(NetworkLog.settings == null) {
NetworkLog activity = (NetworkLog) getActivity();
if(activity != null) {
activity.loadSettings();
}
}
try {
maxLogEntries = NetworkLog.settings.getMaxLogEntries();
} catch (Exception e) {
Log.w("NetworkLog", "Exception getting max log entries: " + e.getMessage(), e);
maxLogEntries = 75000;
}
MyLog.d("LogFragment onCreate");
}
@Override
public void onDestroy() {
super.onDestroy();
MyLog.d("LogFragment onDestroy");
}
@Override
public void onDestroyView() {
super.onDestroyView();
MyLog.d("LogFragment onDestroyView");
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
MyLog.d("[LogFragment] onCreateView");
LinearLayout layout = new LinearLayout(getActivity().getApplicationContext());
layout.setOrientation(LinearLayout.VERTICAL);
ListView listView = new ListView(getActivity().getApplicationContext());
listView.setAdapter(adapter);
listView.setTextFilterEnabled(true);
listView.setFastScrollEnabled(true);
listView.setSmoothScrollbarEnabled(false);
listView.setTranscriptMode(ListView.TRANSCRIPT_MODE_NORMAL);
listView.setStackFromBottom(true);
listView.setOnItemClickListener(new CustomOnItemClickListener());
layout.addView(listView);
registerForContextMenu(listView);
startUpdater();
return layout;
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
MenuInflater inflater = getActivity().getMenuInflater();
inflater.inflate(R.layout.log_context_menu, menu);
AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
ListItem listItem = listData.get(info.position);
if(NetworkLogService.toastBlockedApps.get(listItem.app.packageName) != null) {
menu.findItem(R.id.log_toggle_app_notifications).setTitle(R.string.enable_notifications);
} else {
menu.findItem(R.id.log_toggle_app_notifications).setTitle(R.string.disable_notifications);
}
if(NetworkLogService.blockedApps.get(listItem.app.packageName) != null) {
menu.findItem(R.id.log_toggle_app_logging).setTitle(R.string.unblock_app);
} else {
menu.findItem(R.id.log_toggle_app_logging).setTitle(R.string.block_app);
}
}
@Override
public boolean onContextItemSelected(MenuItem item) {
if(!(item.getMenuInfo() instanceof AdapterContextMenuInfo))
return super.onContextItemSelected(item);
AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
ListItem listItem = listData.get(info.position);
switch(item.getItemId()) {
case R.id.log_copy_src_ip:
copySourceIp(listItem);
return true;
case R.id.log_copy_dst_ip:
copyDestIp(listItem);
return true;
case R.id.log_whois_src_ip:
whoisSourceIp(listItem);
return true;
case R.id.log_whois_dst_ip:
whoisDestIp(listItem);
return true;
case R.id.log_graph:
showGraph(listItem);
return true;
case R.id.log_toggle_app_notifications:
if(NetworkLogService.toastBlockedApps.remove(listItem.app.packageName) == null) {
NetworkLogService.toastBlockedApps.put(listItem.app.packageName, listItem.app.packageName);
}
new SelectToastApps().saveBlockedApps(NetworkLog.context, NetworkLogService.toastBlockedApps);
return true;
case R.id.log_toggle_app_logging:
if(NetworkLogService.blockedApps.remove(listItem.app.packageName) == null) {
NetworkLogService.blockedApps.put(listItem.app.packageName, listItem.app.packageName);
if (NetworkLogService.instance != null) {
Iptables.ignoreApp(NetworkLog.context, listItem.app.uid);
}
} else {
if (NetworkLogService.instance != null) {
Iptables.unignoreApp(NetworkLog.context, listItem.app.uid);
}
}
new SelectBlockedApps().saveBlockedApps(NetworkLog.context, NetworkLogService.blockedApps);
return true;
default:
return super.onContextItemSelected(item);
}
}
@SuppressWarnings("deprecation")
public void copySourceIp(ListItem item) {
String srcAddr;
String srcPort;
if(NetworkLog.resolveHosts && NetworkLog.resolveCopies) {
String resolved = NetworkLog.resolver.resolveAddress(item.srcAddr);
if(resolved != null) {
srcAddr = resolved;
} else {
srcAddr = item.srcAddr;
}
} else {
srcAddr = item.srcAddr;
}
if(NetworkLog.resolvePorts && NetworkLog.resolveCopies) {
srcPort = NetworkLog.resolver.resolveService(String.valueOf(item.srcPort));
} else {
srcPort = String.valueOf(item.srcPort);
}
ClipboardManager clipboard = (ClipboardManager) getActivity().getSystemService(Context.CLIPBOARD_SERVICE);
/* newer API 11 clipboard unsupported on older devices
ClipData clip = ClipData.newPlainText("NetworkLog Source IP", srcAddr + ":" + srcPort);
clipboard.setPrimaryClip(clip);
*/
/* use older deprecated ClipboardManager to support older devices */
clipboard.setText(srcAddr + ":" + srcPort);
}
@SuppressWarnings("deprecation")
public void copyDestIp(ListItem item) {
String dstAddr;
String dstPort;
if(NetworkLog.resolveHosts && NetworkLog.resolveCopies) {
String resolved = NetworkLog.resolver.resolveAddress(item.dstAddr);
if(resolved != null) {
dstAddr = resolved;
} else {
dstAddr = item.dstAddr;
}
} else {
dstAddr = item.dstAddr;
}
if(NetworkLog.resolvePorts && NetworkLog.resolveCopies) {
dstPort = NetworkLog.resolver.resolveService(String.valueOf(item.dstPort));
} else {
dstPort = String.valueOf(item.dstPort);
}
ClipboardManager clipboard = (ClipboardManager) getActivity().getSystemService(Context.CLIPBOARD_SERVICE);
/* newer API 11 clipboard unsupported on older devices
ClipData clip = ClipData.newPlainText("NetworkLog Dest IP", dstAddr + ":" + dstPort);
clipboard.setPrimaryClip(clip);
*/
/* use older deprecated ClipboardManager to support older devices */
clipboard.setText(dstAddr + ":" + dstPort);
}
public void whoisSourceIp(ListItem item) {
String srcAddr;
if(NetworkLog.resolveHosts) {
String resolved = NetworkLog.resolver.resolveAddress(item.srcAddr);
if(resolved != null) {
srcAddr = resolved;
} else {
srcAddr = item.srcAddr;
}
} else {
srcAddr = item.srcAddr;
}
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.whois.com/whois/" + srcAddr)));
}
public void whoisDestIp(ListItem item) {
String dstAddr;
if(NetworkLog.resolveHosts) {
String resolved = NetworkLog.resolver.resolveAddress(item.dstAddr);
if(resolved != null) {
dstAddr = resolved;
} else {
dstAddr = item.dstAddr;
}
} else {
dstAddr = item.dstAddr;
}
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.whois.com/whois/" + dstAddr)));
}
public void showGraph(ListItem item) {
startActivity(new Intent(getActivity().getApplicationContext(), AppTimelineGraph.class)
.putExtra("app_uid", item.app.uid)
.putExtra("src_addr", item.srcAddr)
.putExtra("src_port", item.srcPort)
.putExtra("dst_addr", item.dstAddr)
.putExtra("dst_port", item.dstPort));
}
private class CustomOnItemClickListener implements OnItemClickListener {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
showGraph(listData.get(position));
}
}
public void startUpdater() {
if(updater != null) {
updater.stop();
}
updater = new ListViewUpdater();
new Thread(updater, "LogFragmentUpdater").start();
}
public void onNewLogEntry(final LogEntry entry) {
if(listDataBuffer == null) {
return;
}
if(!entry.isValid()) {
return;
}
ApplicationsTracker.AppEntry appEntry = ApplicationsTracker.uidMap.get(entry.uidString);
if(appEntry == null) {
if(MyLog.enabled) {
MyLog.d("LogFragment: No appEntry for uid " + entry.uid);
}
return;
}
final ListItem item = new ListItem(appEntry);
item.in = entry.in;
item.out = entry.out;
item.srcAddr = entry.src;
item.srcPort = entry.spt;
item.dstAddr = entry.dst;
item.dstPort = entry.dpt;
item.proto = entry.proto;
item.len = entry.len;
item.timestamp = entry.timestamp;
if(MyLog.enabled && MyLog.level >= 6) {
MyLog.d(6, "LogFragment: NewLogEntry: [" + item.app.uidString + "] in=" + item.in + " out=" + item.out + " " + item.srcAddr + ":" + item.srcPort + " --> " + item.dstAddr + ":" + item.dstPort + " proto=" + item.proto + " len=" + item.len);
}
synchronized(listDataBuffer) {
listDataBuffer.add(item);
while(listDataBuffer.size() > maxLogEntries) {
if(MyLog.enabled) {
MyLog.d("Log buffer size reached maxLogEntries limit; truncating");
}
listDataBuffer.removeFirst();
}
}
}
public void clearLogEntriesOlderThan(long timerange) {
MyLog.d("Clearing logFragment entries older than " + timerange);
// Add any items in listDataBuffer to listDataUnfiltered
synchronized(listDataBuffer) {
synchronized(listDataUnfiltered) {
for(ListItem item : listDataBuffer) {
if(MyLog.enabled) {
MyLog.d("Adding buffer item " + item);
}
listDataUnfiltered.add(item);
}
listDataBuffer.clear();
}
}
long timestamp = System.currentTimeMillis() - timerange;
MyLog.d("Setting timestamp " + timestamp);
// Remove items older than timerange
synchronized(listDataUnfiltered) {
Iterator<ListItem> iterator = listDataUnfiltered.iterator();
while(iterator.hasNext()) {
ListItem item = iterator.next();
if(MyLog.enabled) {
MyLog.d("Checking item " + item.app.uid + " " + item.app.name + " " + item.timestamp);
}
if(item.timestamp < timestamp) {
if(MyLog.enabled) {
MyLog.d("Removing item");
}
iterator.remove();
} else {
// remaining entries should be >= timestamp
break;
}
}
synchronized(listData) {
listData.clear();
listData.addAll(listDataUnfiltered);
}
}
NetworkLog.handler.post(new Runnable() {
public void run() {
if(NetworkLog.filterTextInclude.length() > 0 || NetworkLog.filterTextExclude.length() > 0) {
setFilter("");
} else {
refreshAdapter();
}
}
});
}
public void removeApp(String packageName) {
if(listData == null || listDataBuffer == null || listDataUnfiltered == null) {
return;
}
synchronized(listDataBuffer) {
synchronized(listDataUnfiltered) {
synchronized(listData) {
ListItem item;
Iterator<ListItem> iterator;
iterator = listDataBuffer.iterator();
while(iterator.hasNext()) {
item = iterator.next();
if(item.app.packageName.equals(packageName)) {
iterator.remove();
}
}
iterator = listDataUnfiltered.iterator();
while(iterator.hasNext()) {
item = iterator.next();
if(item.app.packageName.equals(packageName)) {
iterator.remove();
}
}
iterator = listData.iterator();
while(iterator.hasNext()) {
item = iterator.next();
if(item.app.packageName.equals(packageName)) {
iterator.remove();
}
}
}
}
}
if(NetworkLog.filterTextInclude.length() > 0 || NetworkLog.filterTextExclude.length() > 0) {
setFilter("");
} else {
refreshAdapter();
}
}
public void pruneLogEntries() {
if(listData == null || listDataBuffer == null || listDataUnfiltered == null) {
return;
}
synchronized(listDataBuffer) {
while(listDataBuffer.size() > maxLogEntries) {
listDataBuffer.removeFirst();
}
}
synchronized(listDataUnfiltered) {
while(listDataUnfiltered.size() > maxLogEntries) {
listDataUnfiltered.removeFirst();
}
}
synchronized(listData) {
while(listData.size() > maxLogEntries) {
listData.removeFirst();
}
}
refreshAdapter();
}
public void stopUpdater() {
if(updater != null) {
updater.stop();
}
}
public boolean appFragmentNeedsRebuild = false;
Runnable updaterRunner = new Runnable() {
public void run() {
if(MyLog.enabled && MyLog.level >= 4) {
MyLog.d(4, "LogFragmentUpdater enter");
}
if(listDataBuffer == null || listData == null || listDataUnfiltered == null) {
return;
}
int i = 0;
boolean included = true;
boolean excluded = false;
long start = System.currentTimeMillis();
synchronized(listDataBuffer) {
synchronized(listData) {
synchronized(listDataUnfiltered) {
for(ListItem item : listDataBuffer) {
if(NetworkLog.filterTextInclude.length() > 0) {
included = testIncludeFilter(item);
}
if(NetworkLog.filterTextExclude.length() > 0) {
excluded = testExcludeFilter(item);
}
if(included == true && excluded == false) {
listData.add(item);
}
listDataUnfiltered.add(item);
i++;
}
listDataBuffer.clear();
}
}
}
synchronized(listDataUnfiltered) {
while(listDataUnfiltered.size() > maxLogEntries) {
listDataUnfiltered.removeFirst();
}
}
synchronized(listData) {
while(listData.size() > maxLogEntries) {
listData.removeFirst();
}
}
refreshAdapter();
long elapsed = System.currentTimeMillis() - start;
if(MyLog.enabled && MyLog.level >= 4) {
MyLog.d(4, "LogFragmentUpdater exit: added " + i + " items -- elapsed: " + elapsed);
}
if(appFragmentNeedsRebuild) {
appFragmentNeedsRebuild = false;
NetworkLog.appFragment.rebuildLogEntries();
NetworkLog.appFragment.updaterRunOnce();
}
}
};
public void updaterRunOnce() {
NetworkLog.handler.post(updaterRunner);
}
// todo: this is largely duplicated in AppFragment -- move to its own file
private class ListViewUpdater implements Runnable {
boolean running = false;
public void stop() {
running = false;
}
public void run() {
running = true;
MyLog.d("Starting LogFragmentUpdater " + this);
while(running) {
if(needsRefresh == true || (listDataBuffer != null && listDataBuffer.size() > 0)) {
updaterRunOnce();
needsRefresh = false;
}
try {
Thread.sleep(1000);
}
catch(Exception e) {
Log.d("NetworkLog", "LogFragmentListUpdater", e);
}
}
if(MyLog.enabled) {
MyLog.d("Stopped LogFragment updater " + this);
}
}
}
public void setFilter(CharSequence s) {
// MyLog.d("[LogFragment] setFilter(" + s + ")");
if(adapter != null) {
adapter.getFilter().filter(s);
}
}
String srcAddrResolved;
String srcPortResolved;
String dstAddrResolved;
String dstPortResolved;
String iface;
boolean matched;
public boolean testIncludeFilter(ListItem item) {
matched = false;
if(NetworkLog.resolveHosts) {
srcAddrResolved = NetworkLog.resolver.resolveAddress(item.srcAddr);
if(srcAddrResolved == null) {
srcAddrResolved = "";
}
dstAddrResolved = NetworkLog.resolver.resolveAddress(item.dstAddr);
if(dstAddrResolved == null) {
dstAddrResolved = "";
}
} else {
srcAddrResolved = "";
dstAddrResolved = "";
}
if(NetworkLog.resolvePorts) {
srcPortResolved = NetworkLog.resolver.resolveService(String.valueOf(item.srcPort));
dstPortResolved = NetworkLog.resolver.resolveService(String.valueOf(item.dstPort));
} else {
srcPortResolved = "";
dstPortResolved = "";
}
if(item.in != null && item.in.length() > 0) {
iface = item.in;
} else {
iface = item.out;
}
for(String c : NetworkLog.filterTextIncludeList) {
if((NetworkLog.filterNameInclude && item.app.nameLowerCase.contains(c))
|| (NetworkLog.filterUidInclude && item.app.uidString.equals(c))
|| (NetworkLog.filterAddressInclude &&
((item.srcAddr.contains(c) || StringPool.getLowerCase(srcAddrResolved).contains(c))
|| (item.dstAddr.contains(c) || StringPool.getLowerCase(dstAddrResolved).contains(c))))
|| (NetworkLog.filterPortInclude &&
((String.valueOf(item.srcPort).equals(c) || StringPool.getLowerCase(srcPortResolved).equals(c))
|| (String.valueOf(item.dstPort).equals(c) || StringPool.getLowerCase(dstPortResolved).equals(c))))
|| (NetworkLog.filterInterfaceInclude && iface.contains(c))
|| (NetworkLog.filterProtocolInclude &&
(item.proto.equals(c) || StringPool.getLowerCase(NetworkLog.resolver.resolveProtocol(item.proto)).equals(c))))
{
matched = true;
break;
}
}
return matched;
}
boolean testExcludeFilter(ListItem item) {
matched = false;
if(NetworkLog.resolveHosts) {
srcAddrResolved = NetworkLog.resolver.resolveAddress(item.srcAddr);
if(srcAddrResolved == null) {
srcAddrResolved = "";
}
dstAddrResolved = NetworkLog.resolver.resolveAddress(item.dstAddr);
if(dstAddrResolved == null) {
dstAddrResolved = "";
}
} else {
srcAddrResolved = "";
dstAddrResolved = "";
}
if(NetworkLog.resolvePorts) {
srcPortResolved = NetworkLog.resolver.resolveService(String.valueOf(item.srcPort)); // fixme: get from stringpool
dstPortResolved = NetworkLog.resolver.resolveService(String.valueOf(item.dstPort)); // fixme: get from stringpool
} else {
srcPortResolved = "";
dstPortResolved = "";
}
if(item.in != null && item.in.length() > 0) {
iface = item.in;
} else {
iface = item.out;
}
for(String c : NetworkLog.filterTextExcludeList) {
if((NetworkLog.filterNameExclude && item.app.nameLowerCase.contains(c))
|| (NetworkLog.filterUidExclude && item.app.uidString.equals(c))
|| (NetworkLog.filterAddressExclude && ((item.srcAddr.contains(c) || StringPool.getLowerCase(srcAddrResolved).contains(c)) || (item.dstAddr.contains(c) || StringPool.getLowerCase(dstAddrResolved).contains(c))))
|| (NetworkLog.filterPortExclude && ((String.valueOf(item.srcPort).equals(c) || StringPool.getLowerCase(srcPortResolved).equals(c)) || (String.valueOf(item.dstPort).equals(c) || StringPool.getLowerCase(dstPortResolved).equals(c))))
|| (NetworkLog.filterInterfaceExclude && iface.contains(c))
|| (NetworkLog.filterProtocolExclude &&
(item.proto.equals(c) || StringPool.getLowerCase(NetworkLog.resolver.resolveProtocol(item.proto)).equals(c))))
{
matched = true;
break;
}
}
return matched;
}
private class CustomAdapter extends ArrayAdapter<ListItem> implements Filterable {
LayoutInflater mInflater = (LayoutInflater) getActivity().getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
CustomFilter filter;
public CustomAdapter(Context context, int resource, List<ListItem> objects) {
super(context, resource, objects);
}
private class CustomFilter extends Filter {
FilterResults results = new FilterResults();
@Override
protected FilterResults performFiltering(CharSequence constraint) {
ArrayList<ListItem> originalItems = new ArrayList<ListItem>(listDataUnfiltered.size());
ArrayList<ListItem> filteredItems = new ArrayList<ListItem>(listDataUnfiltered.size());
int[] includedItemsIndex = new int[listDataUnfiltered.size()];
int includedItemsPos = 0;
int iteratorPos = -1;
ListItem item;
doNotRefresh = true;
if(MyLog.enabled) {
MyLog.d("[LogFragment] performFiltering");
}
synchronized(listDataUnfiltered) {
originalItems.addAll(listDataUnfiltered);
}
if(NetworkLog.filterTextInclude.length() == 0 && NetworkLog.filterTextExclude.length() == 0) {
MyLog.d("[LogFragment] no constraint item count: " + originalItems.size());
results.values = originalItems;
results.count = originalItems.size();
} else {
if(MyLog.enabled) {
MyLog.d("[LogFragment] item count: " + originalItems.size());
}
if(NetworkLog.filterTextIncludeList.size() > 0) {
Iterator<ListItem> iterator = originalItems.iterator();
while(iterator.hasNext()) {
item = iterator.next();
iteratorPos++;
if(MyLog.enabled) {
MyLog.d("[LogFragment] testing filtered item " + item + "; includes: [" + NetworkLog.filterTextInclude + "]");
}
matched = testIncludeFilter(item);
if(matched) {
if(MyLog.enabled) {
MyLog.d("[LogFragment] adding filtered item " + item);
}
includedItemsIndex[includedItemsPos++] = iteratorPos;
}
}
} else {
int count = originalItems.size();
for(int i = 0; i < count; i++) {
includedItemsIndex[includedItemsPos++] = i;
}
}
if(NetworkLog.filterTextExcludeList.size() > 0) {
for(int i = 0; i < includedItemsPos; i++) {
item = originalItems.get(includedItemsIndex[i]);
if(MyLog.enabled) {
MyLog.d("[LogFragment] testing filtered item " + item + "; excludes: [" + NetworkLog.filterTextExclude + "]");
}
matched = testExcludeFilter(item);
if(matched) {
if(MyLog.enabled) {
MyLog.d("[LogFragment] excluding filtered item " + item);
}
} else {
filteredItems.add(item);
}
}
} else {
// no exclusion filter, add all included items to filteredItems
for(int i = 0; i < includedItemsPos; i++) {
filteredItems.add(originalItems.get(includedItemsIndex[i]));
}
}
results.values = filteredItems;
results.count = filteredItems.size();
}
if(MyLog.enabled) {
MyLog.d("[LogFragment] filter returning " + results.count + " items");
}
return results;
}
@SuppressWarnings("unchecked")
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
if(MyLog.enabled) {
MyLog.d("[LogFragment] Publishing filter results");
}
synchronized(listData) {
listData.clear();
listData.addAll((ArrayList<ListItem>) results.values);
if(MyLog.enabled) {
MyLog.d("[LogFilter] listdata size after filter: " + listData.size());
}
}
doNotRefresh = false;
refreshAdapter();
}
}
@Override
public CustomFilter getFilter() {
if(filter == null) {
filter = new CustomFilter();
}
return filter;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
ImageView icon;
TextView name;
TextView iface;
final TextView srcAddr;
TextView srcPort;
final TextView dstAddr;
TextView dstPort;
TextView len;
TextView timestamp;
final ListItem item = getItem(position);
if(convertView == null) {
convertView = mInflater.inflate(R.layout.logitem, null);
holder = new ViewHolder(convertView);
convertView.setTag(holder);
}
holder = (ViewHolder) convertView.getTag();
icon = holder.getIcon();
icon.setTag(item.app.packageName);
icon.setImageDrawable(ApplicationsTracker.loadIcon(getActivity().getApplicationContext(), icon, item.app.packageName));
name = holder.getName();
name.setText("(" + item.app.uid + ")" + " " + item.app.name);
iface = holder.getInterface();
String proto;
if(item.proto != null && item.proto.length() > 0) {
proto = NetworkLog.resolver.resolveProtocol(item.proto) + "/";
} else {
proto = "";
}
if(item.in != null && item.in.length() != 0) {
iface.setText(proto + item.in);
} else {
iface.setText(proto + item.out);
}
srcAddr = holder.getSrcAddr();
srcAddr.setTag(item.srcAddr);
if(NetworkLog.resolveHosts) {
String resolved = NetworkLog.resolver.getResolvedAddress(item.srcAddr);
if(resolved == null) {
NetworkResolverUpdater updater = new NetworkResolverUpdater() {
public void run() {
String tag = (String) srcAddr.getTag();
if(tag != null && tag.equals(item.srcAddr)) {
srcAddr.setText("SRC: " + resolved);
}
}
};
resolved = NetworkLog.resolver.resolveAddress(item.srcAddr, updater);
}
if(resolved != null) {
srcAddr.setText("SRC: " + resolved);
} else {
srcAddr.setText("SRC: " + item.srcAddr);
}
} else {
srcAddr.setText("SRC: " + item.srcAddr);
}
srcPort = holder.getSrcPort();
if(NetworkLog.resolvePorts) {
srcPort.setText(NetworkLog.resolver.resolveService(String.valueOf(item.srcPort)));
} else {
srcPort.setText(String.valueOf(item.srcPort));
}
dstAddr = holder.getDstAddr();
dstAddr.setTag(item.dstAddr);
if(NetworkLog.resolveHosts) {
String resolved = NetworkLog.resolver.getResolvedAddress(item.dstAddr);
if(resolved == null) {
NetworkResolverUpdater updater = new NetworkResolverUpdater() {
public void run() {
String tag = (String) dstAddr.getTag();
if(tag != null && tag.equals(item.dstAddr)) {
dstAddr.setText("DST: " + resolved);
}
}
};
resolved = NetworkLog.resolver.resolveAddress(item.dstAddr, updater);
}
if(resolved != null) {
dstAddr.setText("DST: " + resolved);
} else {
dstAddr.setText("DST: " + item.dstAddr);
}
} else {
dstAddr.setText("DST: " + item.dstAddr);
}
dstPort = holder.getDstPort();
if(NetworkLog.resolvePorts) {
dstPort.setText(NetworkLog.resolver.resolveService(String.valueOf(item.dstPort)));
} else {
dstPort.setText(String.valueOf(item.dstPort));
}
len = holder.getLen();
len.setText("LEN: " + item.len);
timestamp = holder.getTimestamp();
timestamp.setText(Timestamp.getTimestamp(item.timestamp));
return convertView;
}
}
private class ViewHolder {
private View mView;
private ImageView mIcon = null;
private TextView mName = null;
private TextView mInterface = null;
private TextView mSrcAddr = null;
private TextView mSrcPort = null;
private TextView mDstAddr = null;
private TextView mDstPort = null;
private TextView mLen = null;
private TextView mTimestamp = null;
public ViewHolder(View view) {
mView = view;
}
public ImageView getIcon() {
if(mIcon == null) {
mIcon = (ImageView) mView.findViewById(R.id.logIcon);
}
return mIcon;
}
public TextView getName() {
if(mName == null) {
mName = (TextView) mView.findViewById(R.id.logName);
}
return mName;
}
public TextView getInterface() {
if(mInterface == null) {
mInterface = (TextView) mView.findViewById(R.id.logInterface);
}
return mInterface;
}
public TextView getSrcAddr() {
if(mSrcAddr == null) {
mSrcAddr = (TextView) mView.findViewById(R.id.srcAddr);
}
return mSrcAddr;
}
public TextView getSrcPort() {
if(mSrcPort == null) {
mSrcPort = (TextView) mView.findViewById(R.id.srcPort);
}
return mSrcPort;
}
public TextView getDstAddr() {
if(mDstAddr == null) {
mDstAddr = (TextView) mView.findViewById(R.id.dstAddr);
}
return mDstAddr;
}
public TextView getDstPort() {
if(mDstPort == null) {
mDstPort = (TextView) mView.findViewById(R.id.dstPort);
}
return mDstPort;
}
public TextView getLen() {
if(mLen == null) {
mLen = (TextView) mView.findViewById(R.id.len);
}
return mLen;
}
public TextView getTimestamp() {
if(mTimestamp == null) {
mTimestamp = (TextView) mView.findViewById(R.id.timestamp);
}
return mTimestamp;
}
}
}