@Override
        protected Void doInBackground(String... args) {
            if (isCancelled()) {
                return null;
            }
            // TODO subscribe to network events instead of using this
            if (!networkAvailable) {
                Toast.makeText(
                        context,
                        getString(R.string.toast_nonetwork),
                        Toast.LENGTH_LONG).show();
            } else {
                // TODO remove this but with caution
                updateUIBean = new UpdateUIBean();
                // TODO to test different configs change the files poiting by CONFIG_FILE
                //  avoid changing the code directly
                Config.readConfigFile(ReplayConstants.CONFIG_FILE, context);
                SharedPreferences sharedPrefs =
                        PreferenceManager.getDefaultSharedPreferences(context);
                try {
                    // metadata here is user's network type device used geolocation if permitted etc
                    // Google storage forbids to store user related data
                    // So we send that data to a private server
                    server = sharedPrefs.getString("pref_server", "wehe2.meddle.mobi");
                    metadataServer = "wehe-metadata.meddle.mobi";
                    // We first resolve the IP of the server and then communicate with the server
                    // Using IP only, because we have multiple server under same domain and we want
                    // the client not to switch server during a test run
                    // TODO come up with a better way to handle Inet related queries, since this
                    //  introduced inefficiency
                    final InetAddress[] address = {null, null};
                    new Thread() {
                        public void run() {
                            while (!(address[0] instanceof Inet4Address || address[0] instanceof Inet6Address)) {
                                try {
                                    server = InetAddress.getByName(server).getHostAddress();
                                    address[0] = InetAddress.getByName(server);
                                } catch (UnknownHostException e) {
                                    Log.w("GetReplayServerIP", "get IP of replay server failed!");
                                    e.printStackTrace();
                                }
                            }
                        }
                    }.start();
                    new Thread() {
                        public void run() {
                            while (!(address[1] instanceof Inet4Address || address[1] instanceof Inet6Address)) {
                                try {
                                    metadataServer = InetAddress.getByName(metadataServer).getHostAddress();
                                    address[1] = InetAddress.getByName(metadataServer);
                                } catch (UnknownHostException e) {
                                    Log.w("GetReplayServerIP", "get IP of replay server failed!");
                                    e.printStackTrace();
                                }
                            }
                        }
                    }.start();
                    int maxWaitTime = 5000;
                    int currentWaitTime = 500;
                    while (!(address[0] instanceof Inet4Address || address[0] instanceof Inet6Address)
                            && !(address[1] instanceof Inet4Address || address[1] instanceof Inet6Address)) {
                        try {
                            if (currentWaitTime <= maxWaitTime) {
                                Thread.sleep(currentWaitTime);
                                currentWaitTime += 500;
                            } else {
                                Toast.makeText(context, R.string.server_unavailable,
                                        Toast.LENGTH_LONG).show();
                                return null;
                            }
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    if (address[0] instanceof Inet6Address)
                        server = "[" + server + "]";
                    if (address[1] instanceof Inet6Address)
                        metadataServer = "[" + metadataServer + "]";
                    try {
                        CertificateFactory cf = CertificateFactory.getInstance("X.509");
                        Certificate ca;
                        try (InputStream caInput = getResources().openRawResource(R.raw.main)) {
                            ca = cf.generateCertificate(caInput);
                            System.out.println("main=" + ((X509Certificate) ca).getIssuerDN());
                        }
                        // Create a KeyStore containing our trusted CAs
                        String keyStoreType = KeyStore.getDefaultType();
                        KeyStore keyStore = KeyStore.getInstance(keyStoreType);
                        keyStore.load(null, null);
                        keyStore.setCertificateEntry("main", ca);
                        // Create a TrustManager that trusts the CAs in our KeyStore
                        String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
                        TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
                        tmf.init(keyStore);
                        // Create an SSLContext that uses our TrustManager
                        SSLContext context = SSLContext.getInstance("TLS");
                        context.init(null, tmf.getTrustManagers(), null);
                        sslSocketFactory = context.getSocketFactory();
                        hostnameVerifier = (hostname, session) -> true;
                    } catch (CertificateException e) {
                        e.printStackTrace();
                    } catch (NoSuchAlgorithmException e) {
                        e.printStackTrace();
                    } catch (KeyStoreException e) {
                        e.printStackTrace();
                    } catch (KeyManagementException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    try {
                        CertificateFactory cf = CertificateFactory.getInstance("X.509");
                        Certificate ca;
                        try (InputStream caInput = getResources().openRawResource(R.raw.metadata)) {
                            ca = cf.generateCertificate(caInput);
                            System.out.println("metadata=" + ((X509Certificate) ca).getIssuerDN());
                        }
                        // Create a KeyStore containing our trusted CAs
                        String keyStoreType = KeyStore.getDefaultType();
                        KeyStore keyStore = KeyStore.getInstance(keyStoreType);
                        keyStore.load(null, null);
                        keyStore.setCertificateEntry("metadata", ca);
                        // Create a TrustManager that trusts the CAs in our KeyStore
                        String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
                        TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
                        tmf.init(keyStore);
                        // Create an SSLContext that uses our TrustManager
                        SSLContext context = SSLContext.getInstance("TLS");
                        context.init(null, tmf.getTrustManagers(), null);
                        metadataSocketFactory = context.getSocketFactory();
                    } catch (CertificateException e) {
                        e.printStackTrace();
                    } catch (NoSuchAlgorithmException e) {
                        e.printStackTrace();
                    } catch (KeyStoreException e) {
                        e.printStackTrace();
                    } catch (KeyManagementException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    Log.d("GetReplayServerIP", "Server IP: " + server);
                } catch (NullPointerException e) {
                    e.printStackTrace();
                    Log.w("GetReplayServerIP", "Invalid IP address!");
                }
                // Extract data that was sent by previous activity. In our case, list of
                // apps, server and timing
                enableTiming = "true";
                doTest = false;
                int port = Integer.valueOf(Config.get("result_port"));
                analyzerServerUrl = ("https://" + server + ":" + port + "/Results");
                date = new Date();
                results = new JSONArray();
                Log.d("Result Channel",
                        "path: " + server + " port: " + port);
                confirmationReplays = sharedPrefs.getBoolean("confirmationReplays", true);
                // generate or retrieve an id for this phone
                boolean hasID = sharedPrefs.getBoolean("hasID", false);
                if (!hasID) {
                    randomID = new RandomString(10).nextString();
                    SharedPreferences.Editor editor = sharedPrefs.edit();
                    editor.putBoolean("hasID", true);
                    editor.putString("ID", randomID);
                    editor.apply();
                } else {
                    randomID = sharedPrefs.getString("ID", null);
                }
                a_threshold = Integer.parseInt(Objects.requireNonNull(sharedPrefs.getString("pref_threshold_area", "10")));
                ks2pvalue_threshold = Integer.parseInt(Objects.requireNonNull(sharedPrefs.getString("pref_threshold_ks2p", "5")));
                confirmationReplays = sharedPrefs.getBoolean("pref_multiple_tests", true);
                // to get historyCount
                settings = getSharedPreferences(STATUS, Context.MODE_PRIVATE);
                // generate or retrieve an historyCount for this phone
                boolean hasHistoryCount = settings.getBoolean("hasHistoryCount", false);
                if (!hasHistoryCount) {
                    historyCount = 0;
                    SharedPreferences.Editor editor = settings.edit();
                    editor.putBoolean("hasHistoryCount", true);
                    editor.putInt("historyCount", historyCount);
                    editor.apply();
                } else {
                    historyCount = settings.getInt("historyCount", -1);
                }
                // check if retrieve historyCount succeeded
                if (historyCount == -1)
                    throw new RuntimeException();
                Config.set("timing", enableTiming);
                // make sure server is initialized!
                while (server == null) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                Config.set("server", server);
                Config.set("jitter", "true");
                Config.set("publicIP", "");
                new Thread(new Runnable() {
                    public void run() {
                        Config.set("publicIP", getPublicIP("80"));
                    }
                }).start();
                // Find a way to switch to no wait
                while (Config.get("publicIP").equals("")) {
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                Log.d("Replay", "public IP: " + Config.get("publicIP"));
            }
            for (ApplicationBean app : selectedApps) {
                rerun = false;
                // Set the app to run test for
                this.app = app;
                // Run the test on this.app
                runTest();
            }
            // Keep checking if the user exited from ReplayActivity or not
            // TODO find a better way stop the tests immediately without continues checking
            if (isCancelled()) {
                return null;
            }
            if (results.length() > 0) {
                Log.d("Result Channel", "Storing results");
                saveResults();
            }
            if (isCancelled()) {
                return null;
            }
            showFinishDialog();
            Log.d("Result Channel", "Exiting normally");
            return null;
        }
@Override
        protected Void doInBackground(String... args) {
            if (isCancelled()) {
                return null;
            }
           
            if (!networkAvailable) {
                Toast.makeText(
                        context,
                        getString(R.string.toast_nonetwork),
                        Toast.LENGTH_LONG).show();
            } else {
               
                updateUIBean = new UpdateUIBean();
               
               
                Config.readConfigFile(ReplayConstants.CONFIG_FILE, context);
                SharedPreferences sharedPrefs =
                        PreferenceManager.getDefaultSharedPreferences(context);
                try {
                   
                   
                   
                    server = sharedPrefs.getString("pref_server", "wehe2.meddle.mobi");
                    metadataServer = "wehe-metadata.meddle.mobi";
                   
                   
                   
                   
                   
                    final InetAddress[] address = {null, null};
                    new Thread() {
                        public void run() {
                            while (!(address[0] instanceof Inet4Address || address[0] instanceof Inet6Address)) {
                                try {
                                    server = InetAddress.getByName(server).getHostAddress();
                                    address[0] = InetAddress.getByName(server);
                                } catch (UnknownHostException e) {
                                    Log.w("GetReplayServerIP", "get IP of replay server failed!");
                                    e.printStackTrace();
                                }
                            }
                        }
                    }.start();
                    new Thread() {
                        public void run() {
                            while (!(address[1] instanceof Inet4Address || address[1] instanceof Inet6Address)) {
                                try {
                                    metadataServer = InetAddress.getByName(metadataServer).getHostAddress();
                                    address[1] = InetAddress.getByName(metadataServer);
                                } catch (UnknownHostException e) {
                                    Log.w("GetReplayServerIP", "get IP of replay server failed!");
                                    e.printStackTrace();
                                }
                            }
                        }
                    }.start();
                    int maxWaitTime = 5000;
                    int currentWaitTime = 500;
                    while (!(address[0] instanceof Inet4Address || address[0] instanceof Inet6Address)
                            && !(address[1] instanceof Inet4Address || address[1] instanceof Inet6Address)) {
                        try {
                            if (currentWaitTime <= maxWaitTime) {
                                Thread.sleep(currentWaitTime);
                                currentWaitTime += 500;
                            } else {
                                Toast.makeText(context, R.string.server_unavailable,
                                        Toast.LENGTH_LONG).show();
                                return null;
                            }
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    if (address[0] instanceof Inet6Address)
                        server = "[" + server + "]";
                    if (address[1] instanceof Inet6Address)
                        metadataServer = "[" + metadataServer + "]";
                    try {
                        CertificateFactory cf = CertificateFactory.getInstance("X.509");
                        Certificate ca;
                        try (InputStream caInput = getResources().openRawResource(R.raw.main)) {
                            ca = cf.generateCertificate(caInput);
                            System.out.println("main=" + ((X509Certificate) ca).getIssuerDN());
                        }
                       
                        String keyStoreType = KeyStore.getDefaultType();
                        KeyStore keyStore = KeyStore.getInstance(keyStoreType);
                        keyStore.load(null, null);
                        keyStore.setCertificateEntry("main", ca);
                       
                        String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
                        TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
                        tmf.init(keyStore);
                       
                        SSLContext context = SSLContext.getInstance("TLS");
                        context.init(null, tmf.getTrustManagers(), null);
                        sslSocketFactory = context.getSocketFactory();
                        hostnameVerifier = (hostname, session) -> true;
                    } catch (CertificateException e) {
                        e.printStackTrace();
                    } catch (NoSuchAlgorithmException e) {
                        e.printStackTrace();
                    } catch (KeyStoreException e) {
                        e.printStackTrace();
                    } catch (KeyManagementException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    try {
                        CertificateFactory cf = CertificateFactory.getInstance("X.509");
                        Certificate ca;
                        try (InputStream caInput = getResources().openRawResource(R.raw.metadata)) {
                            ca = cf.generateCertificate(caInput);
                            System.out.println("metadata=" + ((X509Certificate) ca).getIssuerDN());
                        }
                       
                        String keyStoreType = KeyStore.getDefaultType();
                        KeyStore keyStore = KeyStore.getInstance(keyStoreType);
                        keyStore.load(null, null);
                        keyStore.setCertificateEntry("metadata", ca);
                       
                        String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
                        TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
                        tmf.init(keyStore);
                       
                        SSLContext context = SSLContext.getInstance("TLS");
                        context.init(null, tmf.getTrustManagers(), null);
                        metadataSocketFactory = context.getSocketFactory();
                    } catch (CertificateException e) {
                        e.printStackTrace();
                    } catch (NoSuchAlgorithmException e) {
                        e.printStackTrace();
                    } catch (KeyStoreException e) {
                        e.printStackTrace();
                    } catch (KeyManagementException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    Log.d("GetReplayServerIP", "Server IP: " + server);
                } catch (NullPointerException e) {
                    e.printStackTrace();
                    Log.w("GetReplayServerIP", "Invalid IP address!");
                }
               
               
                enableTiming = "true";
                doTest = false;
                int port = Integer.valueOf(Config.get("result_port"));
                analyzerServerUrl = ("https://" + server + ":" + port + "/Results");
                date = new Date();
                results = new JSONArray();
                Log.d("Result Channel",
                        "path: " + server + " port: " + port);
                confirmationReplays = sharedPrefs.getBoolean("confirmationReplays", true);
               
                boolean hasID = sharedPrefs.getBoolean("hasID", false);
                if (!hasID) {
                    randomID = new RandomString(10).nextString();
                    SharedPreferences.Editor editor = sharedPrefs.edit();
                    editor.putBoolean("hasID", true);
                    editor.putString("ID", randomID);
                    editor.apply();
                } else {
                    randomID = sharedPrefs.getString("ID", null);
                }
                a_threshold = Integer.parseInt(Objects.requireNonNull(sharedPrefs.getString("pref_threshold_area", "10")));
                ks2pvalue_threshold = Integer.parseInt(Objects.requireNonNull(sharedPrefs.getString("pref_threshold_ks2p", "5")));
                confirmationReplays = sharedPrefs.getBoolean("pref_multiple_tests", true);
               
                settings = getSharedPreferences(STATUS, Context.MODE_PRIVATE);
               
                boolean hasHistoryCount = settings.getBoolean("hasHistoryCount", false);
                if (!hasHistoryCount) {
                    historyCount = 0;
                    SharedPreferences.Editor editor = settings.edit();
                    editor.putBoolean("hasHistoryCount", true);
                    editor.putInt("historyCount", historyCount);
                    editor.apply();
                } else {
                    historyCount = settings.getInt("historyCount", -1);
                }
               
                if (historyCount == -1)
                    throw new RuntimeException();
                Config.set("timing", enableTiming);
               
                while (server == null) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                Config.set("server", server);
                Config.set("jitter", "true");
                Config.set("publicIP", "");
                new Thread(new Runnable() {
                    public void run() {
                        Config.set("publicIP", getPublicIP("80"));
                    }
                }).start();
               
                while (Config.get("publicIP").equals("")) {
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                Log.d("Replay", "public IP: " + Config.get("publicIP"));
            }
            for (ApplicationBean app : selectedApps) {
                rerun = false;
               
                this.app = app;
               
                runTest();
            }
           
           
            if (isCancelled()) {
                return null;
            }
            if (results.length() > 0) {
                Log.d("Result Channel", "Storing results");
                saveResults();
            }
            if (isCancelled()) {
                return null;
            }
            showFinishDialog();
            Log.d("Result Channel", "Exiting normally");
            return null;
        }
@override protected void doinbackground(string... args) { if (iscancelled()) { return null; } if (!networkavailable) { toast.maketext( context, getstring(r.string.toast_nonetwork), toast.length_long).show(); } else { updateuibean = new updateuibean(); config.readconfigfile(replayconstants.config_file, context); sharedpreferences sharedprefs = preferencemanager.getdefaultsharedpreferences(context); try { server = sharedprefs.getstring("pref_server", "wehe2.meddle.mobi"); metadataserver = "wehe-metadata.meddle.mobi"; final inetaddress[] address = {null, null}; new thread() { public void run() { while (!(address[0] instanceof inet4address || address[0] instanceof inet6address)) { try { server = inetaddress.getbyname(server).gethostaddress(); address[0] = inetaddress.getbyname(server); } catch (unknownhostexception e) { log.w("getreplayserverip", "get ip of replay server failed!"); e.printstacktrace(); } } } }.start(); new thread() { public void run() { while (!(address[1] instanceof inet4address || address[1] instanceof inet6address)) { try { metadataserver = inetaddress.getbyname(metadataserver).gethostaddress(); address[1] = inetaddress.getbyname(metadataserver); } catch (unknownhostexception e) { log.w("getreplayserverip", "get ip of replay server failed!"); e.printstacktrace(); } } } }.start(); int maxwaittime = 5000; int currentwaittime = 500; while (!(address[0] instanceof inet4address || address[0] instanceof inet6address) && !(address[1] instanceof inet4address || address[1] instanceof inet6address)) { try { if (currentwaittime <= maxwaittime) { thread.sleep(currentwaittime); currentwaittime += 500; } else { toast.maketext(context, r.string.server_unavailable, toast.length_long).show(); return null; } } catch (interruptedexception e) { e.printstacktrace(); } } if (address[0] instanceof inet6address) server = "[" + server + "]"; if (address[1] instanceof inet6address) metadataserver = "[" + metadataserver + "]"; try { certificatefactory cf = certificatefactory.getinstance("x.509"); certificate ca; try (inputstream cainput = getresources().openrawresource(r.raw.main)) { ca = cf.generatecertificate(cainput); system.out.println("main=" + ((x509certificate) ca).getissuerdn()); } string keystoretype = keystore.getdefaulttype(); keystore keystore = keystore.getinstance(keystoretype); keystore.load(null, null); keystore.setcertificateentry("main", ca); string tmfalgorithm = trustmanagerfactory.getdefaultalgorithm(); trustmanagerfactory tmf = trustmanagerfactory.getinstance(tmfalgorithm); tmf.init(keystore); sslcontext context = sslcontext.getinstance("tls"); context.init(null, tmf.gettrustmanagers(), null); sslsocketfactory = context.getsocketfactory(); hostnameverifier = (hostname, session) -> true; } catch (certificateexception e) { e.printstacktrace(); } catch (nosuchalgorithmexception e) { e.printstacktrace(); } catch (keystoreexception e) { e.printstacktrace(); } catch (keymanagementexception e) { e.printstacktrace(); } catch (ioexception e) { e.printstacktrace(); } try { certificatefactory cf = certificatefactory.getinstance("x.509"); certificate ca; try (inputstream cainput = getresources().openrawresource(r.raw.metadata)) { ca = cf.generatecertificate(cainput); system.out.println("metadata=" + ((x509certificate) ca).getissuerdn()); } string keystoretype = keystore.getdefaulttype(); keystore keystore = keystore.getinstance(keystoretype); keystore.load(null, null); keystore.setcertificateentry("metadata", ca); string tmfalgorithm = trustmanagerfactory.getdefaultalgorithm(); trustmanagerfactory tmf = trustmanagerfactory.getinstance(tmfalgorithm); tmf.init(keystore); sslcontext context = sslcontext.getinstance("tls"); context.init(null, tmf.gettrustmanagers(), null); metadatasocketfactory = context.getsocketfactory(); } catch (certificateexception e) { e.printstacktrace(); } catch (nosuchalgorithmexception e) { e.printstacktrace(); } catch (keystoreexception e) { e.printstacktrace(); } catch (keymanagementexception e) { e.printstacktrace(); } catch (ioexception e) { e.printstacktrace(); } log.d("getreplayserverip", "server ip: " + server); } catch (nullpointerexception e) { e.printstacktrace(); log.w("getreplayserverip", "invalid ip address!"); } enabletiming = "true"; dotest = false; int port = integer.valueof(config.get("result_port")); analyzerserverurl = ("https://" + server + ":" + port + "/results"); date = new date(); results = new jsonarray(); log.d("result channel", "path: " + server + " port: " + port); confirmationreplays = sharedprefs.getboolean("confirmationreplays", true); boolean hasid = sharedprefs.getboolean("hasid", false); if (!hasid) { randomid = new randomstring(10).nextstring(); sharedpreferences.editor editor = sharedprefs.edit(); editor.putboolean("hasid", true); editor.putstring("id", randomid); editor.apply(); } else { randomid = sharedprefs.getstring("id", null); } a_threshold = integer.parseint(objects.requirenonnull(sharedprefs.getstring("pref_threshold_area", "10"))); ks2pvalue_threshold = integer.parseint(objects.requirenonnull(sharedprefs.getstring("pref_threshold_ks2p", "5"))); confirmationreplays = sharedprefs.getboolean("pref_multiple_tests", true); settings = getsharedpreferences(status, context.mode_private); boolean hashistorycount = settings.getboolean("hashistorycount", false); if (!hashistorycount) { historycount = 0; sharedpreferences.editor editor = settings.edit(); editor.putboolean("hashistorycount", true); editor.putint("historycount", historycount); editor.apply(); } else { historycount = settings.getint("historycount", -1); } if (historycount == -1) throw new runtimeexception(); config.set("timing", enabletiming); while (server == null) { try { thread.sleep(1000); } catch (interruptedexception e) { e.printstacktrace(); } } config.set("server", server); config.set("jitter", "true"); config.set("publicip", ""); new thread(new runnable() { public void run() { config.set("publicip", getpublicip("80")); } }).start(); while (config.get("publicip").equals("")) { try { thread.sleep(500); } catch (interruptedexception e) { e.printstacktrace(); } } log.d("replay", "public ip: " + config.get("publicip")); } for (applicationbean app : selectedapps) { rerun = false; this.app = app; runtest(); } if (iscancelled()) { return null; } if (results.length() > 0) { log.d("result channel", "storing results"); saveresults(); } if (iscancelled()) { return null; } showfinishdialog(); log.d("result channel", "exiting normally"); return null; }