Java tutorial
package com.zhengde163.netguard; /* This file is part of NetGuard. NetGuard is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. NetGuard 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 General Public License for more details. You should have received a copy of the GNU General Public License along with NetGuard. If not, see <http://www.gnu.org/licenses/>. Copyright 2015-2016 by Marcel Bokhorst (M66B) */ import android.Manifest; import android.annotation.TargetApi; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.database.Cursor; import android.net.ConnectivityManager; import android.net.Uri; import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; import android.preference.Preference; import android.preference.PreferenceFragment; import android.preference.PreferenceManager; import android.preference.PreferenceScreen; import android.preference.TwoStatePreference; import android.support.annotation.NonNull; import android.support.v4.app.NavUtils; import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.text.TextUtils; import android.util.Log; import android.util.Xml; import android.view.MenuItem; import android.widget.Toast; import org.xml.sax.Attributes; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.XMLReader; import org.xml.sax.helpers.DefaultHandler; import org.xmlpull.v1.XmlSerializer; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParserFactory; public class ActivitySettings extends AppCompatActivity implements SharedPreferences.OnSharedPreferenceChangeListener { private static final String TAG = "NetGuard.Settings"; private boolean running = false; private boolean phone_state = false; private static final int REQUEST_EXPORT = 1; private static final int REQUEST_IMPORT = 2; private static final int REQUEST_METERED2 = 3; private static final int REQUEST_METERED3 = 4; private static final int REQUEST_METERED4 = 5; private static final int REQUEST_ROAMING_NATIONAL = 6; private static final int REQUEST_ROAMING_INTERNATIONAL = 7; private static final int REQUEST_HOSTS = 8; private AlertDialog dialogFilter = null; private static final Intent INTENT_VPN_SETTINGS = new Intent("android.net.vpn.SETTINGS"); protected void onCreate(Bundle savedInstanceState) { Util.setTheme(this); super.onCreate(savedInstanceState); getFragmentManager().beginTransaction().replace(android.R.id.content, new FragmentSettings()).commit(); getSupportActionBar().setTitle(R.string.menu_settings); running = true; } private PreferenceScreen getPreferenceScreen() { return ((PreferenceFragment) getFragmentManager().findFragmentById(android.R.id.content)) .getPreferenceScreen(); } @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); final PreferenceScreen screen = getPreferenceScreen(); final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); // Handle auto enable Preference pref_auto_enable = screen.findPreference("auto_enable"); pref_auto_enable.setTitle(getString(R.string.setting_auto, prefs.getString("auto_enable", "0"))); // Handle screen delay Preference pref_screen_delay = screen.findPreference("screen_delay"); pref_screen_delay.setTitle(getString(R.string.setting_delay, prefs.getString("screen_delay", "0"))); } @Override protected void onResume() { super.onResume(); // Check if permissions were revoked checkPermissions(); // Listen for preference changes SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); prefs.registerOnSharedPreferenceChangeListener(this); // Listen for interactive state changes IntentFilter ifInteractive = new IntentFilter(); ifInteractive.addAction(Intent.ACTION_SCREEN_ON); ifInteractive.addAction(Intent.ACTION_SCREEN_OFF); // Listen for connectivity updates IntentFilter ifConnectivity = new IntentFilter(); ifConnectivity.addAction(ConnectivityManager.CONNECTIVITY_ACTION); if (Util.hasPhoneStatePermission(this)) { phone_state = true; } } @Override protected void onPause() { super.onPause(); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); prefs.unregisterOnSharedPreferenceChangeListener(this); if (phone_state) { phone_state = false; } } @Override protected void onDestroy() { running = false; if (dialogFilter != null) { dialogFilter.dismiss(); dialogFilter = null; } super.onDestroy(); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: Log.i(TAG, "Up"); NavUtils.navigateUpFromSameTask(this); return true; default: return super.onOptionsItemSelected(item); } } @Override @TargetApi(Build.VERSION_CODES.M) public void onSharedPreferenceChanged(SharedPreferences prefs, String name) { Object value = prefs.getAll().get(name); if (value instanceof String && "".equals(value)) prefs.edit().remove(name).apply(); // Dependencies if ("whitelist_wifi".equals(name) || "screen_wifi".equals(name)) ServiceSinkhole.reload("changed " + name, this); else if ("ip6".equals(name)) ServiceSinkhole.reload("changed " + name, this); } @TargetApi(Build.VERSION_CODES.M) private void checkPermissions() { PreferenceScreen screen = getPreferenceScreen(); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); // Check if permission was revoked if (prefs.getBoolean("whitelist_roaming", false)) if (!Util.hasPhoneStatePermission(this)) { prefs.edit().putBoolean("whitelist_roaming", false).apply(); ((TwoStatePreference) screen.findPreference("whitelist_roaming")).setChecked(false); requestPermissions(new String[] { Manifest.permission.READ_PHONE_STATE }, REQUEST_ROAMING_INTERNATIONAL); } // Check if permission was revoked if (prefs.getBoolean("unmetered_2g", false)) if (!Util.hasPhoneStatePermission(this)) { prefs.edit().putBoolean("unmetered_2g", false).apply(); ((TwoStatePreference) screen.findPreference("unmetered_2g")).setChecked(false); requestPermissions(new String[] { Manifest.permission.READ_PHONE_STATE }, REQUEST_METERED2); } if (prefs.getBoolean("unmetered_3g", false)) if (!Util.hasPhoneStatePermission(this)) { prefs.edit().putBoolean("unmetered_3g", false).apply(); ((TwoStatePreference) screen.findPreference("unmetered_3g")).setChecked(false); requestPermissions(new String[] { Manifest.permission.READ_PHONE_STATE }, REQUEST_METERED3); } if (prefs.getBoolean("unmetered_4g", false)) if (!Util.hasPhoneStatePermission(this)) { prefs.edit().putBoolean("unmetered_4g", false).apply(); ((TwoStatePreference) screen.findPreference("unmetered_4g")).setChecked(false); requestPermissions(new String[] { Manifest.permission.READ_PHONE_STATE }, REQUEST_METERED4); } // Check if permission was revoked if (prefs.getBoolean("national_roaming", false)) if (!Util.hasPhoneStatePermission(this)) { prefs.edit().putBoolean("national_roaming", false).apply(); ((TwoStatePreference) screen.findPreference("national_roaming")).setChecked(false); requestPermissions(new String[] { Manifest.permission.READ_PHONE_STATE }, REQUEST_ROAMING_NATIONAL); } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { PreferenceScreen screen = getPreferenceScreen(); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); boolean granted = (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED); if (requestCode == REQUEST_METERED2) { prefs.edit().putBoolean("unmetered_2g", granted).apply(); ((TwoStatePreference) screen.findPreference("unmetered_2g")).setChecked(granted); } else if (requestCode == REQUEST_METERED3) { prefs.edit().putBoolean("unmetered_3g", granted).apply(); ((TwoStatePreference) screen.findPreference("unmetered_3g")).setChecked(granted); } else if (requestCode == REQUEST_METERED4) { prefs.edit().putBoolean("unmetered_4g", granted).apply(); ((TwoStatePreference) screen.findPreference("unmetered_4g")).setChecked(granted); } else if (requestCode == REQUEST_ROAMING_NATIONAL) { prefs.edit().putBoolean("national_roaming", granted).apply(); ((TwoStatePreference) screen.findPreference("national_roaming")).setChecked(granted); } else if (requestCode == REQUEST_ROAMING_INTERNATIONAL) { prefs.edit().putBoolean("whitelist_roaming", granted).apply(); ((TwoStatePreference) screen.findPreference("whitelist_roaming")).setChecked(granted); } if (granted) ServiceSinkhole.reload("permission granted", this); } @Override protected void onActivityResult(int requestCode, int resultCode, final Intent data) { Log.i(TAG, "onActivityResult request=" + requestCode + " result=" + requestCode + " ok=" + (resultCode == RESULT_OK)); if (requestCode == REQUEST_EXPORT) { if (resultCode == RESULT_OK && data != null) handleExport(data); } else if (requestCode == REQUEST_IMPORT) { if (resultCode == RESULT_OK && data != null) handleImport(data); } else if (requestCode == REQUEST_HOSTS) { if (resultCode == RESULT_OK && data != null) handleHosts(data); } else { Log.w(TAG, "Unknown activity result request=" + requestCode); super.onActivityResult(requestCode, resultCode, data); } } private void handleExport(final Intent data) { new AsyncTask<Object, Object, Throwable>() { @Override protected Throwable doInBackground(Object... objects) { OutputStream out = null; try { Uri target = data.getData(); if (data.hasExtra("org.openintents.extra.DIR_PATH")) target = Uri.parse(target + "/netguard_" + new SimpleDateFormat("yyyyMMdd").format(new Date().getTime()) + ".xml"); Log.i(TAG, "Writing URI=" + target); out = getContentResolver().openOutputStream(target); xmlExport(out); return null; } catch (Throwable ex) { Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex)); return ex; } finally { if (out != null) try { out.close(); } catch (IOException ex) { Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex)); } } } @Override protected void onPostExecute(Throwable ex) { if (running) { if (ex == null) Toast.makeText(ActivitySettings.this, R.string.msg_completed, Toast.LENGTH_LONG).show(); else Toast.makeText(ActivitySettings.this, ex.toString(), Toast.LENGTH_LONG).show(); } } }.execute(); } private void handleHosts(final Intent data) { new AsyncTask<Object, Object, Throwable>() { @Override protected Throwable doInBackground(Object... objects) { File hosts = new File(getFilesDir(), "hosts.txt"); FileOutputStream out = null; InputStream in = null; try { Log.i(TAG, "Reading URI=" + data.getData()); in = getContentResolver().openInputStream(data.getData()); out = new FileOutputStream(hosts); int len; long total = 0; byte[] buf = new byte[4096]; while ((len = in.read(buf)) > 0) { out.write(buf, 0, len); total += len; } Log.i(TAG, "Copied bytes=" + total); return null; } catch (Throwable ex) { Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex)); return ex; } finally { if (out != null) try { out.close(); } catch (IOException ex) { Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex)); } if (in != null) try { in.close(); } catch (IOException ex) { Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex)); } } } @Override protected void onPostExecute(Throwable ex) { if (running) { if (ex == null) { SharedPreferences prefs = PreferenceManager .getDefaultSharedPreferences(ActivitySettings.this); String last = SimpleDateFormat.getDateTimeInstance().format(new Date().getTime()); prefs.edit().putString("hosts_last_import", last).apply(); if (running) { getPreferenceScreen().findPreference("use_hosts").setEnabled(true); Toast.makeText(ActivitySettings.this, R.string.msg_completed, Toast.LENGTH_LONG).show(); } ServiceSinkhole.reload("hosts import", ActivitySettings.this); } else Toast.makeText(ActivitySettings.this, ex.toString(), Toast.LENGTH_LONG).show(); } } }.execute(); } private void handleImport(final Intent data) { new AsyncTask<Object, Object, Throwable>() { @Override protected Throwable doInBackground(Object... objects) { InputStream in = null; try { Log.i(TAG, "Reading URI=" + data.getData()); in = getContentResolver().openInputStream(data.getData()); xmlImport(in); return null; } catch (Throwable ex) { Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex)); return ex; } finally { if (in != null) try { in.close(); } catch (IOException ex) { Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex)); } } } @Override protected void onPostExecute(Throwable ex) { if (running) { if (ex == null) { Toast.makeText(ActivitySettings.this, R.string.msg_completed, Toast.LENGTH_LONG).show(); ServiceSinkhole.reloadStats("import", ActivitySettings.this); // Update theme, request permissions recreate(); } else Toast.makeText(ActivitySettings.this, ex.toString(), Toast.LENGTH_LONG).show(); } } }.execute(); } private void xmlExport(OutputStream out) throws IOException { XmlSerializer serializer = Xml.newSerializer(); serializer.setOutput(out, "UTF-8"); serializer.startDocument(null, true); serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); serializer.startTag(null, "netguard"); serializer.startTag(null, "application"); xmlExport(PreferenceManager.getDefaultSharedPreferences(this), serializer); serializer.endTag(null, "application"); serializer.startTag(null, "wifi"); xmlExport(getSharedPreferences("wifi", Context.MODE_PRIVATE), serializer); serializer.endTag(null, "wifi"); serializer.startTag(null, "mobile"); xmlExport(getSharedPreferences("other", Context.MODE_PRIVATE), serializer); serializer.endTag(null, "mobile"); serializer.startTag(null, "screen_wifi"); xmlExport(getSharedPreferences("screen_wifi", Context.MODE_PRIVATE), serializer); serializer.endTag(null, "screen_wifi"); serializer.startTag(null, "screen_other"); xmlExport(getSharedPreferences("screen_other", Context.MODE_PRIVATE), serializer); serializer.endTag(null, "screen_other"); serializer.startTag(null, "apply"); xmlExport(getSharedPreferences("apply", Context.MODE_PRIVATE), serializer); serializer.endTag(null, "apply"); serializer.startTag(null, "notify"); xmlExport(getSharedPreferences("notify", Context.MODE_PRIVATE), serializer); serializer.endTag(null, "notify"); serializer.startTag(null, "filter"); filterExport(serializer); serializer.endTag(null, "filter"); serializer.startTag(null, "forward"); forwardExport(serializer); serializer.endTag(null, "forward"); serializer.endTag(null, "netguard"); serializer.endDocument(); serializer.flush(); } private void xmlExport(SharedPreferences prefs, XmlSerializer serializer) throws IOException { Map<String, ?> settings = prefs.getAll(); for (String key : settings.keySet()) { Object value = settings.get(key); if ("imported".equals(key)) continue; if (value instanceof Boolean) { serializer.startTag(null, "setting"); serializer.attribute(null, "key", key); serializer.attribute(null, "type", "boolean"); serializer.attribute(null, "value", value.toString()); serializer.endTag(null, "setting"); } else if (value instanceof Integer) { serializer.startTag(null, "setting"); serializer.attribute(null, "key", key); serializer.attribute(null, "type", "integer"); serializer.attribute(null, "value", value.toString()); serializer.endTag(null, "setting"); } else if (value instanceof String) { serializer.startTag(null, "setting"); serializer.attribute(null, "key", key); serializer.attribute(null, "type", "string"); serializer.attribute(null, "value", value.toString()); serializer.endTag(null, "setting"); } else if (value instanceof Set) { Set<String> set = (Set<String>) value; serializer.startTag(null, "setting"); serializer.attribute(null, "key", key); serializer.attribute(null, "type", "set"); serializer.attribute(null, "value", TextUtils.join("\n", set)); serializer.endTag(null, "setting"); } else Log.e(TAG, "Unknown key=" + key); } } private void filterExport(XmlSerializer serializer) throws IOException { PackageManager pm = getPackageManager(); Cursor cursor = DatabaseHelper.getInstance(this).getAccess(); int colUid = cursor.getColumnIndex("uid"); int colVersion = cursor.getColumnIndex("version"); int colProtocol = cursor.getColumnIndex("protocol"); int colDAddr = cursor.getColumnIndex("daddr"); int colDPort = cursor.getColumnIndex("dport"); int colTime = cursor.getColumnIndex("time"); int colBlock = cursor.getColumnIndex("block"); while (cursor.moveToNext()) for (String pkg : getPackages(cursor.getInt(colUid))) { serializer.startTag(null, "rule"); serializer.attribute(null, "pkg", pkg); serializer.attribute(null, "version", Integer.toString(cursor.getInt(colVersion))); serializer.attribute(null, "protocol", Integer.toString(cursor.getInt(colProtocol))); serializer.attribute(null, "daddr", cursor.getString(colDAddr)); serializer.attribute(null, "dport", Integer.toString(cursor.getInt(colDPort))); serializer.attribute(null, "time", Long.toString(cursor.getLong(colTime))); serializer.attribute(null, "block", Integer.toString(cursor.getInt(colBlock))); serializer.endTag(null, "rule"); } cursor.close(); } private void forwardExport(XmlSerializer serializer) throws IOException { PackageManager pm = getPackageManager(); Cursor cursor = DatabaseHelper.getInstance(this).getForwarding(); int colProtocol = cursor.getColumnIndex("protocol"); int colDPort = cursor.getColumnIndex("dport"); int colRAddr = cursor.getColumnIndex("raddr"); int colRPort = cursor.getColumnIndex("rport"); int colRUid = cursor.getColumnIndex("ruid"); while (cursor.moveToNext()) for (String pkg : getPackages(cursor.getInt(colRUid))) { serializer.startTag(null, "port"); serializer.attribute(null, "pkg", pkg); serializer.attribute(null, "protocol", Integer.toString(cursor.getInt(colProtocol))); serializer.attribute(null, "dport", Integer.toString(cursor.getInt(colDPort))); serializer.attribute(null, "raddr", cursor.getString(colRAddr)); serializer.attribute(null, "rport", Integer.toString(cursor.getInt(colRPort))); serializer.endTag(null, "port"); } cursor.close(); } private String[] getPackages(int uid) { if (uid == 0) return new String[] { "root" }; else if (uid == 1013) return new String[] { "mediaserver" }; else if (uid == 9999) return new String[] { "nobody" }; else { String pkgs[] = getPackageManager().getPackagesForUid(uid); if (pkgs == null) return new String[0]; else return pkgs; } } private void xmlImport(InputStream in) throws IOException, SAXException, ParserConfigurationException { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); prefs.unregisterOnSharedPreferenceChangeListener(this); prefs.edit().putBoolean("enabled", false).apply(); ServiceSinkhole.stop("import", this); XMLReader reader = SAXParserFactory.newInstance().newSAXParser().getXMLReader(); XmlImportHandler handler = new XmlImportHandler(this); reader.setContentHandler(handler); reader.parse(new InputSource(in)); xmlImport(handler.application, prefs); xmlImport(handler.wifi, getSharedPreferences("wifi", Context.MODE_PRIVATE)); xmlImport(handler.mobile, getSharedPreferences("other", Context.MODE_PRIVATE)); xmlImport(handler.unused, getSharedPreferences("unused", Context.MODE_PRIVATE)); xmlImport(handler.screen_wifi, getSharedPreferences("screen_wifi", Context.MODE_PRIVATE)); xmlImport(handler.screen_other, getSharedPreferences("screen_other", Context.MODE_PRIVATE)); xmlImport(handler.roaming, getSharedPreferences("roaming", Context.MODE_PRIVATE)); xmlImport(handler.apply, getSharedPreferences("apply", Context.MODE_PRIVATE)); xmlImport(handler.notify, getSharedPreferences("notify", Context.MODE_PRIVATE)); // Upgrade imported settings Receiver.upgrade(true, this); // Refresh UI prefs.edit().putBoolean("imported", true).apply(); prefs.registerOnSharedPreferenceChangeListener(this); } private void xmlImport(Map<String, Object> settings, SharedPreferences prefs) { SharedPreferences.Editor editor = prefs.edit(); // Clear existing setting for (String key : prefs.getAll().keySet()) if (!"enabled".equals(key)) editor.remove(key); // Apply new settings for (String key : settings.keySet()) { Object value = settings.get(key); if (value instanceof Boolean) editor.putBoolean(key, (Boolean) value); else if (value instanceof Integer) editor.putInt(key, (Integer) value); else if (value instanceof String) editor.putString(key, (String) value); else if (value instanceof Set) editor.putStringSet(key, (Set<String>) value); else Log.e(TAG, "Unknown type=" + value.getClass()); } editor.apply(); } private class XmlImportHandler extends DefaultHandler { private Context context; public boolean enabled = false; public Map<String, Object> application = new HashMap<>(); public Map<String, Object> wifi = new HashMap<>(); public Map<String, Object> mobile = new HashMap<>(); public Map<String, Object> unused = new HashMap<>(); public Map<String, Object> screen_wifi = new HashMap<>(); public Map<String, Object> screen_other = new HashMap<>(); public Map<String, Object> roaming = new HashMap<>(); public Map<String, Object> apply = new HashMap<>(); public Map<String, Object> notify = new HashMap<>(); private Map<String, Object> current = null; public XmlImportHandler(Context context) { this.context = context; } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) { if (qName.equals("netguard")) ; // Ignore else if (qName.equals("application")) current = application; else if (qName.equals("wifi")) current = wifi; else if (qName.equals("mobile")) current = mobile; else if (qName.equals("unused")) current = unused; else if (qName.equals("screen_wifi")) current = screen_wifi; else if (qName.equals("screen_other")) current = screen_other; else if (qName.equals("roaming")) current = roaming; else if (qName.equals("apply")) current = apply; else if (qName.equals("notify")) current = notify; else if (qName.equals("filter")) { current = null; Log.i(TAG, "Clearing filters"); DatabaseHelper.getInstance(context).clearAccess(); } else if (qName.equals("forward")) { current = null; Log.i(TAG, "Clearing forwards"); DatabaseHelper.getInstance(context).deleteForward(); } else if (qName.equals("setting")) { String key = attributes.getValue("key"); String type = attributes.getValue("type"); String value = attributes.getValue("value"); if (current == null) Log.e(TAG, "No current key=" + key); else { if ("enabled".equals(key)) enabled = Boolean.parseBoolean(value); else { if ("boolean".equals(type)) current.put(key, Boolean.parseBoolean(value)); else if ("integer".equals(type)) current.put(key, Integer.parseInt(value)); else if ("string".equals(type)) current.put(key, value); else if ("set".equals(type)) { Set<String> set = new HashSet<>(); if (!TextUtils.isEmpty(value)) for (String s : value.split("\n")) set.add(s); current.put(key, set); } else Log.e(TAG, "Unknown type key=" + key); } } } else if (qName.equals("rule")) { String pkg = attributes.getValue("pkg"); String version = attributes.getValue("version"); String protocol = attributes.getValue("protocol"); Packet packet = new Packet(); packet.version = (version == null ? 4 : Integer.parseInt(version)); packet.protocol = (protocol == null ? 6 /* TCP */ : Integer.parseInt(protocol)); packet.daddr = attributes.getValue("daddr"); packet.dport = Integer.parseInt(attributes.getValue("dport")); packet.time = Long.parseLong(attributes.getValue("time")); int block = Integer.parseInt(attributes.getValue("block")); try { packet.uid = getUid(pkg); DatabaseHelper.getInstance(context).updateAccess(packet, null, block); } catch (PackageManager.NameNotFoundException ex) { Log.w(TAG, "Package not found pkg=" + pkg); } } else if (qName.equals("port")) { String pkg = attributes.getValue("pkg"); int protocol = Integer.parseInt(attributes.getValue("protocol")); int dport = Integer.parseInt(attributes.getValue("dport")); String raddr = attributes.getValue("raddr"); int rport = Integer.parseInt(attributes.getValue("rport")); try { int uid = getUid(pkg); DatabaseHelper.getInstance(context).addForward(protocol, dport, raddr, rport, uid); } catch (PackageManager.NameNotFoundException ex) { Log.w(TAG, "Package not found pkg=" + pkg); } } else Log.e(TAG, "Unknown element qname=" + qName); } private int getUid(String pkg) throws PackageManager.NameNotFoundException { if ("root".equals(pkg)) return 0; else if ("mediaserver".equals(pkg)) return 1013; else if ("nobody".equals(pkg)) return 9999; else return getPackageManager().getApplicationInfo(pkg, 0).uid; } } }