1 package org.robolectric.shadows; 2 3 import static android.os.Build.VERSION_CODES.R; 4 5 import android.app.ActivityThread; 6 import android.content.ComponentName; 7 import android.content.pm.ApplicationInfo; 8 import android.content.pm.PackageManager; 9 import android.content.pm.ParceledListSlice; 10 import android.os.RemoteException; 11 import android.os.UserHandle; 12 13 import java.lang.reflect.InvocationHandler; 14 import java.lang.reflect.Method; 15 import java.lang.reflect.Proxy; 16 import java.util.Collections; 17 18 import javax.annotation.Nonnull; 19 import org.robolectric.RuntimeEnvironment; 20 import org.robolectric.annotation.Implementation; 21 import org.robolectric.annotation.Implements; 22 23 @Implements(value = ActivityThread.class, isInAndroidSdk = false, looseSignatures = true) 24 public class ShadowActivityThread { 25 private static ApplicationInfo applicationInfo; 26 27 @Implementation getPackageManager()28 public static Object getPackageManager() { 29 ClassLoader classLoader = ShadowActivityThread.class.getClassLoader(); 30 Class<?> iPackageManagerClass; 31 try { 32 iPackageManagerClass = classLoader.loadClass("android.content.pm.IPackageManager"); 33 } catch (ClassNotFoundException e) { 34 throw new RuntimeException(e); 35 } 36 return Proxy.newProxyInstance( 37 classLoader, 38 new Class[] {iPackageManagerClass}, 39 new InvocationHandler() { 40 @Override 41 public Object invoke(Object proxy, @Nonnull Method method, Object[] args) 42 throws Exception { 43 if (method.getName().equals("getApplicationInfo")) { 44 String packageName = (String) args[0]; 45 int flags = (Integer) args[1]; 46 47 if (packageName.equals(ShadowActivityThread.applicationInfo.packageName)) { 48 return ShadowActivityThread.applicationInfo; 49 } 50 51 try { 52 return RuntimeEnvironment.application 53 .getPackageManager() 54 .getApplicationInfo(packageName, flags); 55 } catch (PackageManager.NameNotFoundException e) { 56 throw new RemoteException(e.getMessage()); 57 } 58 } else if (method.getName().equals("getActivityInfo")) { 59 ComponentName className = (ComponentName) args[0]; 60 int flags = (Integer) args[1]; 61 62 try { 63 return RuntimeEnvironment.application 64 .getPackageManager() 65 .getActivityInfo(className, flags); 66 } catch (PackageManager.NameNotFoundException e) { 67 throw new RemoteException(e.getMessage()); 68 } 69 } else if (method.getName().equals("getServiceInfo")) { 70 ComponentName className = (ComponentName) args[0]; 71 int flags = (Integer) args[1]; 72 73 try { 74 return RuntimeEnvironment.application 75 .getPackageManager() 76 .getServiceInfo(className, flags); 77 } catch (PackageManager.NameNotFoundException e) { 78 throw new RemoteException(e.getMessage()); 79 } 80 } else if (method.getName().equals("getInstalledApplications")) { 81 int flags = (Integer) args[0]; 82 int userId = (Integer) args[1]; 83 return new ParceledListSlice<>( 84 RuntimeEnvironment.application 85 .getApplicationContext() 86 .createContextAsUser(UserHandle.of(userId), /* flags= */ 0) 87 .getPackageManager() 88 .getInstalledApplications(flags)); 89 } else if (method.getName().equals("notifyPackageUse")) { 90 return null; 91 } else if (method.getName().equals("getPackageInstaller")) { 92 return null; 93 } 94 throw new UnsupportedOperationException("sorry, not supporting " + method + " yet!"); 95 } 96 }); 97 } 98 99 // BEGIN-INTERNAL 100 @Implementation(minSdk = R) 101 public static Object getPermissionManager() { 102 ClassLoader classLoader = ShadowActivityThread.class.getClassLoader(); 103 Class<?> iPermissionManagerClass; 104 try { 105 iPermissionManagerClass = classLoader.loadClass("android.permission.IPermissionManager"); 106 } catch (ClassNotFoundException e) { 107 throw new RuntimeException(e); 108 } 109 return Proxy.newProxyInstance( 110 classLoader, 111 new Class[] {iPermissionManagerClass}, 112 new InvocationHandler() { 113 @Override 114 public Object invoke(Object proxy, @Nonnull Method method, Object[] args) 115 throws Exception { 116 if (method.getName().equals("getSplitPermissions")) { 117 return Collections.emptyList(); 118 } 119 return method.getDefaultValue(); 120 } 121 }); 122 } 123 // END-INTERNAL 124 125 @Implementation 126 public static Object currentActivityThread() { 127 return RuntimeEnvironment.getActivityThread(); 128 } 129 130 /** 131 * Internal use only. 132 * 133 * @deprecated do not use 134 */ 135 @Deprecated 136 public static void setApplicationInfo(ApplicationInfo applicationInfo) { 137 ShadowActivityThread.applicationInfo = applicationInfo; 138 } 139 } 140