content: package org.lsposed.lspatch.service;
  
  import android.content.Context;
  import android.content.SharedPreferences;
  import android.content.pm.ApplicationInfo;
  import android.os.Environment;
  import android.os.IBinder;
  import android.os.ParcelFileDescriptor;
  import android.os.RemoteException;
  import android.util.Log;
  
  import org.json.JSONArray;
  import org.json.JSONObject;
  import org.lsposed.lspatch.util.ModuleLoader;
  import org.lsposed.lspd.models.Module;
  import org.lsposed.lspd.service.ILSPApplicationService;
  
  import java.io.File;
  import java.util.ArrayList;
  import java.util.Collections;
  import java.util.List;
  
  public class NeoLocalApplicationService extends ILSPApplicationService.Stub {
      private static final String TAG = "NPatch";
      private final List<Module> cachedModule;
      public NeoLocalApplicationService(Context context) {
          cachedModule = Collections.synchronizedList(new ArrayList<>());
          loadModulesFromSharedPreferences(context);
      }
  
      private void loadModulesFromSharedPreferences(Context context) {
          var shared = context.getSharedPreferences("npatch", Context.MODE_PRIVATE);
          try {
              String modulesJsonString = shared.getString("modules", "[]");
              Log.i(TAG, "using local application service with modules:" + modulesJsonString);
  
              if (modulesJsonString.equals("{}")) {
                  modulesJsonString = "[]";
              }
  
              var mArr = new JSONArray(modulesJsonString);
              for (int i = 0; i < mArr.length(); i++) {
                  var mObj = mArr.getJSONObject(i);
                  var m = new Module();
                  m.apkPath = mObj.getString("path");
                  m.packageName = mObj.getString("packageName");
  
                  if (m.apkPath == null || !new File(m.apkPath).exists()) {
                      Log.w(TAG, "Module:" + m.packageName + " path not available, attempting reset.");
                      try {
                          ApplicationInfo info = context.getPackageManager().getApplicationInfo(m.packageName, 0);
                          m.apkPath = info.sourceDir;
                          Log.i(TAG, "Module:" + m.packageName + " path reset to " + m.apkPath);
                      } catch (Exception e) {
                          Log.e(TAG, "Failed to get ApplicationInfo for module: " + m.packageName, e);
                          continue;
                      }
                  }
                  m.file = ModuleLoader.loadModule(m.apkPath);
                  cachedModule.add(m);
              }
          } catch (Throwable e) {
              Log.e(TAG, "Error loading modules from SharedPreferences.", e);
          }
      }
  
      @Override
      public List<Module> getLegacyModulesList() throws RemoteException {
          return cachedModule;
      }
  
      @Override
      public List<Module> getModulesList() throws RemoteException {
          return new ArrayList<>();
      }
  
      @Override
      public String getPrefsPath(String packageName) throws RemoteException {
          return new File(Environment.getDataDirectory(), "data/" + packageName + "/shared_prefs/").getAbsolutePath();
      }
  
      @Override
      public ParcelFileDescriptor requestInjectedManagerBinder(List<IBinder> binder) throws RemoteException {
          return null;
      }
  
      @Override
      public IBinder asBinder() {
          return this;
      }
  
      @Override
      public boolean isLogMuted() throws RemoteException {
          return false;
      }
  }
  