public static String sha1Hash(String filePath) {
   try {
     MessageDigest messageDigest = MessageDigest.getInstance("SHA1");
     FileInputStream fileInputStream = new FileInputStream(filePath);
     byte[] dataBytes = new byte[1024];
     int nread = 0;
     while ((nread = fileInputStream.read(dataBytes)) != -1) {
       messageDigest.update(dataBytes, 0, nread);
     }
     ;
     fileInputStream.close();
     byte[] mdbytes = messageDigest.digest();
     StringBuffer stringBuilder = new StringBuffer("");
     for (int i = 0; i < mdbytes.length; i++) {
       stringBuilder.append(Integer.toString((mdbytes[i] & 0xff) + 0x100, 16).substring(1));
     }
     return stringBuilder.toString();
   } catch (NoSuchAlgorithmException e) {
     RfcxLog.logExc(logTag, e);
   } catch (FileNotFoundException e) {
     RfcxLog.logExc(logTag, e);
   } catch (IOException e) {
     RfcxLog.logExc(logTag, e);
   } catch (Exception e) {
     RfcxLog.logExc(logTag, e);
   }
   return null;
 }
    @Override
    public void run() {
      DeviceScreenShotService deviceScreenShotService = DeviceScreenShotService.this;

      app = (RfcxGuardian) getApplication();
      Context context = app.getApplicationContext();
      DeviceScreenLock deviceScreenLock = new DeviceScreenLock(context, RfcxGuardian.APP_ROLE);

      try {
        // activate screen and set wake lock
        deviceScreenLock.unLockScreen();
        Thread.sleep(3000);

        String[] saveScreenShot = deviceScreenShot.launchCapture(context);
        if (saveScreenShot != null) {
          app.screenShotDb.dbCaptured.insert(
              saveScreenShot[0], saveScreenShot[1], saveScreenShot[2], saveScreenShot[3]);
          Log.i(TAG, "ScreenShot saved: " + saveScreenShot[0] + "." + saveScreenShot[1]);
        }
        Thread.sleep(3000);

      } catch (Exception e) {
        RfcxLog.logExc(TAG, e);
      } finally {
        deviceScreenShotService.runFlag = false;
        app.rfcxServiceHandler.setRunState(SERVICE_NAME, false);
        app.rfcxServiceHandler.stopService(SERVICE_NAME);
        deviceScreenLock.releaseWakeLock();
      }
    }
 public static void deleteDirectoryContents(String directoryFilePath) {
   File directory = new File(directoryFilePath);
   for (File file : directory.listFiles()) {
     try {
       file.delete();
       Log.d(logTag, "Deleted " + file.getName() + " from " + directory.getName() + " directory.");
     } catch (Exception e) {
       RfcxLog.logExc(logTag, e);
     }
   }
 }
 @Override
 public int onStartCommand(Intent intent, int flags, int startId) {
   super.onStartCommand(intent, flags, startId);
   Log.v(logTag, "Starting service: " + logTag);
   this.runFlag = true;
   app.rfcxServiceHandler.setRunState(SERVICE_NAME, true);
   try {
     this.serviceObject.start();
   } catch (IllegalThreadStateException e) {
     RfcxLog.logExc(logTag, e);
   }
   return START_STICKY;
 }
 public static void deleteDirectoryContents(
     String directoryFilePath, List<String> excludeFilePaths) {
   File directory = new File(directoryFilePath);
   for (File file : directory.listFiles()) {
     try {
       if (!excludeFilePaths.contains(file.getAbsolutePath())) {
         file.delete();
         Log.d(
             logTag, "Deleted " + file.getName() + " from " + directory.getName() + " directory.");
       }
     } catch (Exception e) {
       RfcxLog.logExc(logTag, e);
     }
   }
 }
 public static int chmod(File file, int mode) {
   try {
     Class fileUtils = Class.forName("android.os.FileUtils");
     Method setPermissions =
         fileUtils.getMethod("setPermissions", String.class, int.class, int.class, int.class);
     return (Integer) setPermissions.invoke(null, file.getAbsolutePath(), mode, -1, -1);
   } catch (ClassNotFoundException e) {
     RfcxLog.logExc(logTag, e);
   } catch (SecurityException e) {
     RfcxLog.logExc(logTag, e);
   } catch (NoSuchMethodException e) {
     RfcxLog.logExc(logTag, e);
   } catch (IllegalArgumentException e) {
     RfcxLog.logExc(logTag, e);
   } catch (IllegalAccessException e) {
     RfcxLog.logExc(logTag, e);
   } catch (InvocationTargetException e) {
     RfcxLog.logExc(logTag, e);
   } catch (Exception e) {
     RfcxLog.logExc(logTag, e);
   }
   return 0;
 }
    @Override
    public void run() {
      AudioEncodeService serviceInstance = AudioEncodeService.this;

      app = (RfcxGuardian) getApplication();
      Context context = app.getApplicationContext();

      int prefsEncodeSkipThreshold = app.rfcxPrefs.getPrefAsInt("audio_encode_skip_threshold");
      int prefsAudioEncodeCyclePause = app.rfcxPrefs.getPrefAsInt("audio_encode_cycle_pause");
      int prefsAudioBatteryCutoff = app.rfcxPrefs.getPrefAsInt("audio_battery_cutoff");
      long prefsCaptureLoopPeriod = (long) app.rfcxPrefs.getPrefAsInt("audio_cycle_duration");
      int prefsAudioEncodeQuality = app.rfcxPrefs.getPrefAsInt("audio_encode_quality");

      AudioEncodeUtils.cleanupEncodeDirectory(app.audioEncodeDb.dbEncodeQueue.getAllRows());

      while (serviceInstance.runFlag) {

        app.rfcxServiceHandler.reportAsActive(SERVICE_NAME);

        try {

          String[] audioToEncode = app.audioEncodeDb.dbEncodeQueue.getLatestRow();

          // only proceed with encode process if:
          if ( // 1) there is a queued audio file in the database
          (audioToEncode[0] != null)
              // 2) the device internal battery percentage is at or above the minimum charge
              // threshold
              && (app.deviceBattery.getBatteryChargePercentage(context, null)
                  >= prefsAudioBatteryCutoff)) {

            File preEncodeFile = new File(audioToEncode[9]);

            if (!preEncodeFile.exists()) {

              app.audioEncodeDb.dbEncodeQueue.deleteSingleRow(audioToEncode[1]);

            } else if (((int) Integer.parseInt(audioToEncode[10])) >= prefsEncodeSkipThreshold) {

              Log.d(
                  logTag,
                  (new StringBuilder())
                      .append("Skipping AudioEncode ")
                      .append(audioToEncode[1])
                      .append(" after ")
                      .append(prefsEncodeSkipThreshold)
                      .append(" failed attempts")
                      .toString());

              app.audioEncodeDb.dbEncodeQueue.deleteSingleRow(audioToEncode[1]);
              if (preEncodeFile.exists()) {
                preEncodeFile.delete();
              }

            } else {

              try {

                Log.i(
                    logTag,
                    (new StringBuilder())
                        .append("Beginning Encode: ")
                        .append(audioToEncode[1])
                        .append(" ")
                        .append(audioToEncode[2])
                        .append("=>")
                        .append(audioToEncode[6])
                        .toString());

                File postEncodeFile =
                    new File(
                        RfcxAudio.getAudioFileLocation_PostEncode(
                            (long) Long.parseLong(audioToEncode[1]), audioToEncode[6]));
                File gZippedFile =
                    new File(
                        RfcxAudio.getAudioFileLocation_Complete_PostZip(
                            (long) Long.parseLong(audioToEncode[1]),
                            RfcxAudio.getFileExtension(audioToEncode[6])));

                // just in case there's already a post-encoded file, delete it first
                if (postEncodeFile.exists()) {
                  postEncodeFile.delete();
                }

                long encodeStartTime = System.currentTimeMillis();

                // perform audio encoding and set encoding eventual bit rate
                int encodeBitRate =
                    AudioEncodeUtils.encodeAudioFile(
                        preEncodeFile, // source file
                        postEncodeFile, // target file
                        audioToEncode[6], // encoding codec
                        (int) Integer.parseInt(audioToEncode[4]), // encoding sample rate
                        (int) Integer.parseInt(audioToEncode[5]), // encoding target bitrate
                        prefsAudioEncodeQuality // encoding quality
                        );

                long encodeDuration = (System.currentTimeMillis() - encodeStartTime);

                if (encodeBitRate < 0) {

                  app.audioEncodeDb.dbEncodeQueue.incrementSingleRowAttempts(audioToEncode[1]);

                } else {

                  // delete pre-encode file
                  if (preEncodeFile.exists() && postEncodeFile.exists()) {
                    preEncodeFile.delete();
                  }

                  // generate file checksum of encoded file
                  String preZipDigest = FileUtils.sha1Hash(postEncodeFile.getAbsolutePath());

                  // GZIP encoded file into final location
                  GZipUtils.gZipFile(postEncodeFile, gZippedFile);

                  // If successful, cleanup pre-GZIP file and make sure final file is accessible by
                  // other roles (like 'api')
                  if (gZippedFile.exists()) {

                    FileUtils.chmod(gZippedFile, 0777);
                    if (postEncodeFile.exists()) {
                      postEncodeFile.delete();
                    }

                    app.audioEncodeDb.dbEncoded.insert(
                        audioToEncode[1],
                        RfcxAudio.getFileExtension(audioToEncode[6]),
                        preZipDigest,
                        (int) Integer.parseInt(audioToEncode[4]),
                        encodeBitRate,
                        audioToEncode[6],
                        (long) Long.parseLong(audioToEncode[7]),
                        encodeDuration,
                        gZippedFile.getAbsolutePath());

                    app.audioEncodeDb.dbEncodeQueue.deleteSingleRow(audioToEncode[1]);

                    app.rfcxServiceHandler.triggerIntentServiceImmediately("CheckInTrigger");
                  }
                }

              } catch (Exception e) {
                RfcxLog.logExc(logTag, e);
                app.rfcxServiceHandler.setRunState(SERVICE_NAME, false);
                serviceInstance.runFlag = false;
              }
            }
          } else {

            // force a [brief] pause before re-running each cycle
            Thread.sleep(prefsAudioEncodeCyclePause);

            if (app.deviceBattery.getBatteryChargePercentage(context, null)
                < prefsAudioBatteryCutoff) {
              long extendEncodeLoopBy = (2 * prefsCaptureLoopPeriod) - prefsAudioEncodeCyclePause;
              Log.i(
                  logTag,
                  (new StringBuilder())
                      .append("AudioEncode disabled due to low battery level (")
                      .append("current: ")
                      .append(app.deviceBattery.getBatteryChargePercentage(context, null))
                      .append("%, ")
                      .append("required: ")
                      .append(prefsAudioBatteryCutoff)
                      .append("%")
                      .append("). Waiting ")
                      .append((Math.round(2 * prefsCaptureLoopPeriod / 1000)))
                      .append(" seconds before next attempt.")
                      .toString());
              Thread.sleep(extendEncodeLoopBy);
            }
          }

        } catch (Exception e) {
          RfcxLog.logExc(logTag, e);
          app.rfcxServiceHandler.setRunState(SERVICE_NAME, false);
          serviceInstance.runFlag = false;
        }
      }

      app.rfcxServiceHandler.setRunState(SERVICE_NAME, false);
      serviceInstance.runFlag = false;
    }