package com.samknows.measurement.util; import java.net.InetAddress; import java.net.NetworkInterface; import java.net.SocketException; import java.util.Enumeration; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.io.ByteArrayInputStream; import android.app.AlarmManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.os.Build; import android.telephony.TelephonyManager; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.Signature; import android.util.Log; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import javax.security.auth.x500.X500Principal; import com.samknows.libcore.SKPorting; import com.samknows.libcore.SKConstants; import com.samknows.measurement.SK2AppSettings; import com.samknows.measurement.DeviceDescription; import com.samknows.measurement.MainService; import com.samknows.measurement.environment.PhoneIdentityDataCollector; public class OtherUtils { static final String TAG = "OtherUtils"; public static void reschedule(Context ctx, long timeDurationMilliseconds){ long actualSystemTimeMilliseconds; if(SK2AppSettings.getInstance().isWakeUpEnabled()){ actualSystemTimeMilliseconds = rescheduleWakeup(ctx, timeDurationMilliseconds); }else{ actualSystemTimeMilliseconds = rescheduleRTC(ctx, timeDurationMilliseconds); } Log.d(TAG, "Rescheduled to " + TimeUtils.logString(actualSystemTimeMilliseconds) + ", "+ (actualSystemTimeMilliseconds - System.currentTimeMillis()) +" ms from now..."); } public static long rescheduleRTC(Context ctx, long time) { Log.d(TAG, "+++++DEBUG+++++ rescheduleRTC time=" + time); time = checkRescheduleTime(time); Log.d(TAG, "+++++DEBUG+++++ schedule RTC for " + time/1000 + "s from now"); PendingIntent intent = PendingIntent.getService(ctx, 0, new Intent(ctx, MainService.class), PendingIntent.FLAG_UPDATE_CURRENT); AlarmManager manager = (AlarmManager) ctx.getSystemService(Context.ALARM_SERVICE); long systemTimeMilliseconds = System.currentTimeMillis() + time; // AlarmManager.RTC - This does NOT wake-up the device if it is asleep. manager.set(AlarmManager.RTC, systemTimeMilliseconds, intent); SK2AppSettings.getInstance().saveNextRunTime(systemTimeMilliseconds); return systemTimeMilliseconds; } public static void cancelAlarm(Context ctx){ Log.d(TAG, "+++++DEBUG+++++ cancelAlarm"); AlarmManager manager = (AlarmManager) ctx.getSystemService(Context.ALARM_SERVICE); if(PendingIntent.getService(ctx,0, new Intent(ctx, MainService.class), PendingIntent.FLAG_NO_CREATE) == null){ Log.d(TAG, "There is no pending intent for the service"); } PendingIntent intent = PendingIntent.getService(ctx, 0, new Intent(ctx, MainService.class), PendingIntent.FLAG_UPDATE_CURRENT); manager.cancel(intent); SK2AppSettings.getInstance().saveNextRunTime(SKConstants.NO_NEXT_RUN_TIME); } public static long rescheduleWakeup(Context ctx, long time) { Log.d(TAG, "+++++DEBUG+++++ rescheduleWakeup time=" + time); time = checkRescheduleTime(time); Log.d(TAG, "+++++DEBUG+++++ time immediately overridden (by) = checkRescheduleTime to " + time); Log.d(TAG, "+++++DEBUG+++++ schedule RTC_WAKEUP for " + time/1000 + "s from now"); PendingIntent intent = PendingIntent.getService(ctx, 0, new Intent(ctx, MainService.class), PendingIntent.FLAG_UPDATE_CURRENT); AlarmManager manager = (AlarmManager) ctx.getSystemService(Context.ALARM_SERVICE); long systemTimeMilliseconds = System.currentTimeMillis() + time; // AlarmManager.RTC_WAKEUP - This DOES wake-up the device if it is asleep. manager.set(AlarmManager.RTC_WAKEUP, systemTimeMilliseconds, intent); SK2AppSettings.getInstance().saveNextRunTime(systemTimeMilliseconds); return systemTimeMilliseconds; } //if the reschedule time is less than the testStart window play it safe an reschedule the main service for the //the rescheduleTime private static long checkRescheduleTime(long time){ SK2AppSettings a = SK2AppSettings.getSK2AppSettingsInstance(); long ret = time; if(time <= a.getTestStartWindow()){ Log.w(TAG, "reschedule time less than testStartWindow ("+a.getTestStartWindow()+"), changing it to: "+ a.rescheduleTime/1000+"s."); ret = a.rescheduleTime; } return ret; } public String getLocalIpAddress() { try { for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) { NetworkInterface intf = en.nextElement(); for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) { InetAddress inetAddress = enumIpAddr.nextElement(); if (!inetAddress.isLoopbackAddress()) { return inetAddress.getHostAddress(); } } } } catch (SocketException ex) { SKPorting.sAssertE(OtherUtils.class, "failed to get ip address", ex); } return null; } public static boolean isRoaming(Context ctx) { TelephonyManager tm = (TelephonyManager) ctx.getSystemService(Context.TELEPHONY_SERVICE); return tm.isNetworkRoaming(); } public static boolean isPhoneAssosiated(Context ctx) { String imei = PhoneIdentityDataCollector.getImei(ctx); for (DeviceDescription dd : SK2AppSettings.getInstance().getDevices()) { if (dd.isCurrentDevice(imei)) return true; } return false; } public static String stringEncoding(String value){ Pattern p = Pattern.compile("%u([a-zA-Z0-9]{4})"); Matcher m = p.matcher(value); StringBuffer sb = new StringBuffer(); while(m.find()){ m.appendReplacement(sb, String.valueOf((char)Integer.parseInt(m.group(1), 16))); } m.appendTail(sb); return sb.toString(); } public static boolean isThisDeviceAnEmulator() { if (Build.FINGERPRINT.startsWith("generic") || Build.MANUFACTURER.contains("Genymotion")) { // This is probably an Emulator! return true; } // This is a real device! return false; } // http://stackoverflow.com/questions/7085644/how-to-check-if-apk-is-signed-or-debug-build private static final X500Principal DEBUG_DN = new X500Principal("CN=Android Debug,O=Android,C=US"); public static boolean isDebuggable(Context ctx) { if (isThisDeviceAnEmulator()) { return true; } boolean debuggable = false; try { PackageInfo pinfo = ctx.getPackageManager().getPackageInfo(ctx.getPackageName(),PackageManager.GET_SIGNATURES); Signature signatures[] = pinfo.signatures; CertificateFactory cf = CertificateFactory.getInstance("X.509"); // Note that when using Roboelectic, this will return null! if (signatures != null) { for (Signature signature : signatures) { ByteArrayInputStream stream = new ByteArrayInputStream(signature.toByteArray()); X509Certificate cert = (X509Certificate) cf.generateCertificate(stream); debuggable = cert.getSubjectX500Principal().equals(DEBUG_DN); if (debuggable) { break; } } } } catch (NameNotFoundException e) { //debuggable variable will remain false } catch (CertificateException e) { //debuggable variable will remain false } catch (Exception e) { // Don't call SKLogger, as that could be recursive! // SKLogger.sAssert(false); } return debuggable; } }