title: Android: programmatically open Overview/Recents screen in API 24+
body: <p>I am trying to open the Overview/Recents screen in Android. From <a href="https://stackoverflow.com/questions/14267482/android-programmatically-open-recent-apps-dialog/30579544#30579544">Android: Programmatically open &quot;Recent Apps&quot; dialog</a>, I can use the following code:</p>
  
  <pre><code>try {
      Class serviceManagerClass = Class.forName("android.os.ServiceManager");
      Method getService = serviceManagerClass.getMethod("getService", String.class);
      IBinder retbinder = (IBinder) getService.invoke(null, "statusbar");
      Class statusBarClass = Class.forName(retbinder.getInterfaceDescriptor());
      Object statusBarObject = statusBarClass.getClasses()[0]
              .getMethod("asInterface", IBinder.class).invoke(null, retbinder);
      Method toggleRecentApps = statusBarClass.getMethod("toggleRecentApps");
      toggleRecentApps.setAccessible(true);
      toggleRecentApps.invoke(statusBarObject);
  } catch (InvocationTargetException| NoSuchMethodException | RemoteException | IllegalAccessException   | ClassNotFoundException e){
      handleError(e);
  }
  </code></pre>
  
  <p>However, <code>toggleRecentApps()</code> is <a href="https://android.googlesource.com/platform/frameworks/base.git/+/master/core/java/com/android/internal/statusbar/IStatusBarService.aidl" rel="noreferrer">no longer in IStatusBarService</a> since Nougat, and it causes a NoSuchMethodException.</p>
  
  <p>Is there any other way (excluding AccessibilityService) that can be used to open the Overview/Recents screen?</p>
  
  <hr />
  
  <p><strong>EDIT</strong>: The class that implements IStatusBarService seems to be <a href="https://android.googlesource.com/platform/frameworks/base/+/master/services/core/java/com/android/server/statusbar/StatusBarManagerService.java" rel="noreferrer">StatusBarManagerService</a>. However, calling <code>statusBarObject.getClass().getCanonicalName()</code> returns <code>com.android.internal.statusbar.IStatusBarService.Stub.Proxy</code>, so getting an <code>IStatusBar</code> (which does implement <code>toggleRecentApps()</code>) through the private field <code>mBar</code> doesn't seem to be a working way to get it.</p>
  
  <hr />
  
  <p><strong>EDIT 2</strong>: Seeing that StatusBarManagerInternal.java is an interface that contains <code>void toggleRecentApps()</code>, I tried to find its implementation, which I found in <code>StatusBarManagerService</code>:</p>
  
  <pre><code>private final StatusBarManagerInternal mInternalService = new StatusBarManagerInternal() { ... }
  </code></pre>
  
  <p>So it's an anonymous class in StatusManagerService. >:(.</p>
  
  <p>However, I also found:</p>
  
  <pre><code>/**
   * Construct the service, add the status bar view to the window manager
   */
  public StatusBarManagerService(Context context, WindowManagerService windowManager) {
      mContext = context;
      mWindowManager = windowManager;
  
      LocalServices.addService(StatusBarManagerInternal.class, mInternalService);
  }
  </code></pre>
  
  <p>So it apparently registers it in <code>LocalServices</code>, which in turn manages it in an <code>ArrayMap</code>:</p>
  
  <pre><code>private static final ArrayMap&lt;Class&lt;?&gt;, Object&gt; sLocalServiceObjects =
          new ArrayMap&lt;Class&lt;?&gt;, Object&gt;();
  </code></pre>
  
  <p>Therefore, I tried to access it:</p>
  
  <pre><code>try {
      Field services = Class.forName("com.android.server.LocalServices")
              .getDeclaredField("sLocalServiceObjects");
      services.setAccessible(true);
      ArrayMap&lt;Class&lt;?&gt;, Object&gt; serviceMap = (ArrayMap&lt;Class&lt;?&gt;, Object&gt;) services.get(null);
      Set&lt;Map.Entry&lt;Class&lt;?&gt;, Object&gt;&gt; serviceSet = serviceMap.entrySet();
  
      for (Map.Entry&lt;Class&lt;?&gt;, Object&gt; serviceEntry : serviceSet) {
          if (serviceEntry.getKey().isInterface()) {
              if ("com.android.server.statusbar.StatusBarManagerInternal"
                      .equals(serviceEntry.getKey().getName())) {
                  Object statusBarInternalObject = serviceEntry.getValue();
                  Class statusBarInternalClass = serviceEntry.getKey();
                  Method openRecents = statusBarInternalClass.getMethod("toggleRecentApps");
                  openRecents.setAccessible(true);
                  openRecents.invoke(statusBarInternalObject);
                  return;
              }
          }
      }
  } catch (Exception e) {
      handleError(e);
  }
  </code></pre>
  
  <p>However:</p>
  
  <pre><code>/**
   * This class is used in a similar way as ServiceManager, except the services registered here
   * are not Binder objects and are only available in the same process.
   *
   * Once all services are converted to the SystemService interface, this class can be absorbed
   * into SystemServiceManager.
   *
   * {@hide}
   */
  </code></pre>
  
  <p>Alas, I have to be in the SystemUI process (or so it seems) to be able to access it. (Effectively, the <code>ArrayMap</code> is empty, rendering my attempt useless.)</p>
  
  <p>Any guidance on how to proceed from here would be appreciated.</p>