content: package com.genymobile.scrcpy.wrappers;
  
  import com.genymobile.scrcpy.FakeContext;
  import com.genymobile.scrcpy.Ln;
  
  import android.annotation.SuppressLint;
  import android.annotation.TargetApi;
  import android.content.Intent;
  import android.os.Binder;
  import android.os.Build;
  import android.os.Bundle;
  import android.os.IBinder;
  import android.os.IInterface;
  
  import java.lang.reflect.Field;
  import java.lang.reflect.Method;
  
  @SuppressLint("PrivateApi,DiscouragedPrivateApi")
  public final class ActivityManager {
  
      private final IInterface manager;
      private Method getContentProviderExternalMethod;
      private boolean getContentProviderExternalMethodNewVersion = true;
      private Method removeContentProviderExternalMethod;
      private Method startActivityAsUserMethod;
      private Method forceStopPackageMethod;
  
      static ActivityManager create() {
          try {
              // On old Android versions, the ActivityManager is not exposed via AIDL,
              // so use ActivityManagerNative.getDefault()
              Class<?> cls = Class.forName("android.app.ActivityManagerNative");
              Method getDefaultMethod = cls.getDeclaredMethod("getDefault");
              IInterface am = (IInterface) getDefaultMethod.invoke(null);
              return new ActivityManager(am);
          } catch (ReflectiveOperationException e) {
              throw new AssertionError(e);
          }
      }
  
      private ActivityManager(IInterface manager) {
          this.manager = manager;
      }
  
      private Method getGetContentProviderExternalMethod() throws NoSuchMethodException {
          if (getContentProviderExternalMethod == null) {
              try {
                  getContentProviderExternalMethod = manager.getClass()
                          .getMethod("getContentProviderExternal", String.class, int.class, IBinder.class, String.class);
              } catch (NoSuchMethodException e) {
                  // old version
                  getContentProviderExternalMethod = manager.getClass().getMethod("getContentProviderExternal", String.class, int.class, IBinder.class);
                  getContentProviderExternalMethodNewVersion = false;
              }
          }
          return getContentProviderExternalMethod;
      }
  
      private Method getRemoveContentProviderExternalMethod() throws NoSuchMethodException {
          if (removeContentProviderExternalMethod == null) {
              removeContentProviderExternalMethod = manager.getClass().getMethod("removeContentProviderExternal", String.class, IBinder.class);
          }
          return removeContentProviderExternalMethod;
      }
  
      @TargetApi(Build.VERSION_CODES.Q)
      private ContentProvider getContentProviderExternal(String name, IBinder token) {
          try {
              Method method = getGetContentProviderExternalMethod();
              Object[] args;
              if (getContentProviderExternalMethodNewVersion) {
                  // new version
                  args = new Object[]{name, FakeContext.ROOT_UID, token, null};
              } else {
                  // old version
                  args = new Object[]{name, FakeContext.ROOT_UID, token};
              }
              // ContentProviderHolder providerHolder = getContentProviderExternal(...);
              Object providerHolder = method.invoke(manager, args);
              if (providerHolder == null) {
                  return null;
              }
              // IContentProvider provider = providerHolder.provider;
              Field providerField = providerHolder.getClass().getDeclaredField("provider");
              providerField.setAccessible(true);
              Object provider = providerField.get(providerHolder);
              if (provider == null) {
                  return null;
              }
              return new ContentProvider(this, provider, name, token);
          } catch (ReflectiveOperationException e) {
              Ln.e("Could not invoke method", e);
              return null;
          }
      }
  
      void removeContentProviderExternal(String name, IBinder token) {
          try {
              Method method = getRemoveContentProviderExternalMethod();
              method.invoke(manager, name, token);
          } catch (ReflectiveOperationException e) {
              Ln.e("Could not invoke method", e);
          }
      }
  
      public ContentProvider createSettingsProvider() {
          return getContentProviderExternal("settings", new Binder());
      }
  
      private Method getStartActivityAsUserMethod() throws NoSuchMethodException, ClassNotFoundException {
          if (startActivityAsUserMethod == null) {
              Class<?> iApplicationThreadClass = Class.forName("android.app.IApplicationThread");
              Class<?> profilerInfo = Class.forName("android.app.ProfilerInfo");
              startActivityAsUserMethod = manager.getClass()
                      .getMethod("startActivityAsUser", iApplicationThreadClass, String.class, Intent.class, String.class, IBinder.class, String.class,
                              int.class, int.class, profilerInfo, Bundle.class, int.class);
          }
          return startActivityAsUserMethod;
      }
  
      @SuppressWarnings("ConstantConditions")
      public int startActivity(Intent intent) {
          try {
              Method method = getStartActivityAsUserMethod();
              return (int) method.invoke(
                      /* this */ manager,
                      /* caller */ null,
                      /* callingPackage */ FakeContext.PACKAGE_NAME,
                      /* intent */ intent,
                      /* resolvedType */ null,
                      /* resultTo */ null,
                      /* resultWho */ null,
                      /* requestCode */ 0,
                      /* startFlags */ 0,
                      /* profilerInfo */ null,
                      /* bOptions */ null,
                      /* userId */ /* UserHandle.USER_CURRENT */ -2);
          } catch (Throwable e) {
              Ln.e("Could not invoke method", e);
              return 0;
          }
      }
  
      private Method getForceStopPackageMethod() throws NoSuchMethodException {
          if (forceStopPackageMethod == null) {
              forceStopPackageMethod = manager.getClass().getMethod("forceStopPackage", String.class, int.class);
          }
          return forceStopPackageMethod;
      }
  
      public void forceStopPackage(String packageName) {
          try {
              Method method = getForceStopPackageMethod();
              method.invoke(manager, packageName, /* userId */ /* UserHandle.USER_CURRENT */ -2);
          } catch (Throwable e) {
              Ln.e("Could not invoke method", e);
          }
      }
  }
  