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 android.app.Activity; 22 import android.content.Context; 23 import android.content.Intent; 24 import android.content.pm.ResolveInfo; 25 import android.graphics.Point; 26 import android.view.View; 27 import android.view.WindowManager; 28 29 import com.android.launcher3.Launcher; 30 31 import org.robolectric.Robolectric; 32 import org.robolectric.RuntimeEnvironment; 33 import org.robolectric.android.controller.ActivityController; 34 import org.robolectric.shadows.ShadowLooper; 35 import org.robolectric.util.ReflectionHelpers; 36 37 import java.util.List; 38 39 /** 40 * Utility class to help manage Launcher UI and related objects for test. 41 */ 42 public class LauncherUIHelper { 43 44 /** 45 * Returns the class name for the Launcher activity as defined in the manifest 46 */ getLauncherClassName()47 public static String getLauncherClassName() { 48 Context context = RuntimeEnvironment.application; 49 Intent homeIntent = new Intent(Intent.ACTION_MAIN) 50 .addCategory(Intent.CATEGORY_HOME) 51 .setPackage(context.getPackageName()) 52 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 53 54 List<ResolveInfo> launchers = context.getPackageManager() 55 .queryIntentActivities(homeIntent, 0); 56 if (launchers.size() != 1) { 57 return null; 58 } 59 return launchers.get(0).activityInfo.name; 60 } 61 62 /** 63 * Returns an activity controller for Launcher activity defined in the manifest 64 */ buildLauncher()65 public static <T extends Launcher> ActivityController<T> buildLauncher() { 66 try { 67 Class<T> tClass = (Class<T>) Class.forName(getLauncherClassName()); 68 return Robolectric.buildActivity(tClass); 69 } catch (Exception e) { 70 throw new RuntimeException(e); 71 } 72 } 73 74 /** 75 * Creates and binds a Launcher activity defined in the manifest. 76 * Note that the model must be bound before calling this 77 */ buildAndBindLauncher()78 public static <T extends Launcher> T buildAndBindLauncher() { 79 ActivityController<T> controller = buildLauncher(); 80 81 T launcher = controller.setup().get(); 82 doLayout(launcher); 83 ViewOnDrawExecutor executor = ReflectionHelpers.getField(launcher, "mPendingExecutor"); 84 if (executor != null) { 85 executor.runAllTasks(); 86 } 87 return launcher; 88 } 89 90 /** 91 * Performs a measure and layout pass for the given activity 92 */ doLayout(Activity activity)93 public static void doLayout(Activity activity) { 94 Point size = new Point(); 95 RuntimeEnvironment.application.getSystemService(WindowManager.class) 96 .getDefaultDisplay().getSize(size); 97 View view = activity.getWindow().getDecorView(); 98 view.measure(makeMeasureSpec(size.x, EXACTLY), makeMeasureSpec(size.y, EXACTLY)); 99 view.layout(0, 0, size.x, size.y); 100 ShadowLooper.idleMainLooper(); 101 } 102 } 103