content: package org.opencv.engine;
  
  import android.app.Service;
  import android.content.Intent;
  import android.content.pm.PackageManager.NameNotFoundException;
  import android.content.res.XmlResourceParser;
  import android.os.IBinder;
  import android.os.RemoteException;
  import android.util.Log;
  import android.text.TextUtils;
  import java.io.File;
  import java.lang.reflect.Field;
  import java.util.ArrayList;
  import java.util.Arrays;
  import java.util.List;
  import org.xmlpull.v1.XmlPullParser;
  
  public class OpenCVEngineService extends Service {
      private static final String TAG = "OpenCVEngine/Service";
      private IBinder mEngineInterface = null;
      private List<LibVariant> variants = new ArrayList<LibVariant>();
  
      private class LibVariant {
          public String version;
          public List<String> files;
  
          public void parseFile(XmlResourceParser p) {
              try {
                  int eventType = p.getEventType();
                  while (eventType != XmlPullParser.END_DOCUMENT) {
                      if (eventType == XmlPullParser.START_TAG) {
                          if (p.getName().equals("library")) {
                              parseLibraryTag(p);
                          } else if (p.getName().equals("file")) {
                              parseFileTag(p);
                          }
                      }
                      eventType = p.next();
                  }
              } catch (Exception e) {
                  Log.e(TAG, "Failed to parse xml library descriptor");
              }
          }
  
          private void parseLibraryTag(XmlResourceParser p) {
              version = p.getAttributeValue(null, "version");
              files = new ArrayList<String>();
          }
  
          private void parseFileTag(XmlResourceParser p) {
              files.add(p.getAttributeValue(null, "name"));
          }
  
          public boolean hasAllFiles(String path) {
              boolean result = true;
              List<String> actualFiles = Arrays.asList((new File(path)).list());
              for (String f : files)
                  result &= actualFiles.contains(f);
              return result;
          }
  
          public boolean isCompatible(String v) {
              String[] expected = v.split("\\.");
              String[] actual = version.split("\\.");
              int i = 0;
              for (; i < Math.min(expected.length, actual.length); ++i) {
                  int diff = Integer.valueOf(expected[i])
                          - Integer.valueOf(actual[i]);
                  if (diff > 0 || (diff != 0 && i == 0)) {
                      // requested version is greater than actual OR major version differs
                      return false;
                  } else if (diff < 0) {
                      // version is compatible
                      return true;
                  }
              }
              if (expected.length > i) {
                  // requested version is longer than actual - 2.4.11.2 and 2.4.11
                  return false;
              }
              return true;
          }
  
          public String getFileList() {
              return TextUtils.join(";", files);
          }
      }
  
      public void onCreate() {
          Log.d(TAG, "Service starting");
          for (Field field : R.xml.class.getDeclaredFields()) {  // Build error here means that all config.xml files are missing (configuration problem)
              Log.d(TAG, "Found config: " + field.getName());
              final LibVariant lib = new LibVariant();
              try {
                  final int id = field.getInt(R.xml.class);
                  final XmlResourceParser p = getResources().getXml(id);
                  lib.parseFile(p);
              } catch (IllegalArgumentException e) {
                  e.printStackTrace();
              } catch (IllegalAccessException e) {
                  e.printStackTrace();
              }
              if (lib.version != null
                      && lib.files.size() != 0
                      && lib.hasAllFiles(getApplication().getApplicationInfo().nativeLibraryDir)) {
                  variants.add(lib);
              Log.d(TAG, "Added config: " + lib.version);
              }
          }
          super.onCreate();
          mEngineInterface = new OpenCVEngineInterface.Stub() {
  
              @Override
              public boolean installVersion(String version)
                      throws RemoteException {
                  // DO NOTHING
                  return false;
              }
  
              @Override
              public String getLibraryList(String version) throws RemoteException {
                  Log.i(TAG, "getLibraryList(" + version + ")");
                  for (LibVariant lib : variants) {
                      Log.i(TAG, "checking " + lib.version + " ...");
                      if (lib.isCompatible(version))
                          return lib.getFileList();
                  }
                  return null;
              }
  
              @Override
              public String getLibPathByVersion(String version)
                      throws RemoteException {
                  // TODO: support API 8
                  return getApplication().getApplicationInfo().nativeLibraryDir;
              }
  
              @Override
              public int getEngineVersion() throws RemoteException {
                  int version = 3450;
                  try {
                      version = getPackageManager().getPackageInfo(getPackageName(), 0).versionCode;
                  } catch (NameNotFoundException e) {
                      e.printStackTrace();
                  }
                  return version / 1000;
              }
          };
      }
  
      public IBinder onBind(Intent intent) {
          Log.i(TAG, "Service onBind called for intent " + intent.toString());
          return mEngineInterface;
      }
  
      public boolean onUnbind(Intent intent) {
          Log.i(TAG, "Service onUnbind called for intent " + intent.toString());
          return true;
      }
  
      public void OnDestroy() {
          Log.i(TAG, "OpenCV Engine service destruction");
      }
  
  }
  