1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.launcher3.util; 17 18 import static android.view.View.MeasureSpec.EXACTLY; 19 import static android.view.View.MeasureSpec.makeMeasureSpec; 20 21 import static com.android.launcher3.Utilities.createHomeIntent; 22 23 import android.app.Activity; 24 import android.content.Context; 25 import android.content.Intent; 26 import android.content.pm.ResolveInfo; 27 import android.graphics.Point; 28 import android.view.View; 29 import android.view.WindowManager; 30 31 import com.android.launcher3.Launcher; 32 33 import org.robolectric.Robolectric; 34 import org.robolectric.RuntimeEnvironment; 35 import org.robolectric.android.controller.ActivityController; 36 import org.robolectric.shadows.ShadowLooper; 37 import org.robolectric.util.ReflectionHelpers; 38 39 import java.util.List; 40 41 /** 42 * Utility class to help manage Launcher UI and related objects for test. 43 */ 44 public class LauncherUIHelper { 45 46 /** 47 * Returns the class name for the Launcher activity as defined in the manifest 48 */ getLauncherClassName()49 public static String getLauncherClassName() { 50 Context context = RuntimeEnvironment.application; 51 Intent homeIntent = createHomeIntent().setPackage(context.getPackageName()); 52 53 List<ResolveInfo> launchers = context.getPackageManager() 54 .queryIntentActivities(homeIntent, 0); 55 if (launchers.size() != 1) { 56 return null; 57 } 58 return launchers.get(0).activityInfo.name; 59 } 60 61 /** 62 * Returns an activity controller for Launcher activity defined in the manifest 63 */ buildLauncher()64 public static <T extends Launcher> ActivityController<T> buildLauncher() { 65 try { 66 Class<T> tClass = (Class<T>) Class.forName(getLauncherClassName()); 67 return Robolectric.buildActivity(tClass); 68 } catch (Exception e) { 69 throw new RuntimeException(e); 70 } 71 } 72 73 /** 74 * Creates and binds a Launcher activity defined in the manifest. 75 * Note that the model must be bound before calling this 76 */ buildAndBindLauncher()77 public static <T extends Launcher> T buildAndBindLauncher() { 78 ActivityController<T> controller = buildLauncher(); 79 80 T launcher = controller.setup().get(); 81 doLayout(launcher); 82 ViewOnDrawExecutor executor = ReflectionHelpers.getField(launcher, "mPendingExecutor"); 83 if (executor != null) { 84 executor.runAllTasks(); 85 } 86 return launcher; 87 } 88 89 /** 90 * Performs a measure and layout pass for the given activity 91 */ doLayout(Activity activity)92 public static void doLayout(Activity activity) { 93 Point size = new Point(); 94 RuntimeEnvironment.application.getSystemService(WindowManager.class) 95 .getDefaultDisplay().getSize(size); 96 View view = activity.getWindow().getDecorView(); 97 view.measure(makeMeasureSpec(size.x, EXACTLY), makeMeasureSpec(size.y, EXACTLY)); 98 view.layout(0, 0, size.x, size.y); 99 ShadowLooper.idleMainLooper(); 100 } 101 } 102