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