blob: 49ff238a43f577191e903a88704d1267e4f33346 [file] [log] [blame]
/**
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.android.quickstep;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import android.app.prediction.AppPredictor;
import android.app.prediction.AppTarget;
import android.app.prediction.AppTargetId;
import android.content.ComponentName;
import android.content.pm.LauncherActivityInfo;
import android.os.Process;
import android.view.View;
import androidx.test.filters.LargeTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.Launcher;
import com.android.launcher3.appprediction.PredictionRowView;
import com.android.launcher3.appprediction.PredictionUiStateManager;
import com.android.launcher3.appprediction.PredictionUiStateManager.Client;
import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.model.AppLaunchTracker;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.ArrayList;
import java.util.List;
@LargeTest
@RunWith(AndroidJUnit4.class)
public class AppPredictionsUITests extends AbstractQuickStepTest {
private LauncherActivityInfo mSampleApp1;
private LauncherActivityInfo mSampleApp2;
private LauncherActivityInfo mSampleApp3;
private AppPredictor.Callback mCallback;
@Before
public void setUp() throws Exception {
super.setUp();
List<LauncherActivityInfo> activities = LauncherAppsCompat.getInstance(mTargetContext)
.getActivityList(null, Process.myUserHandle());
mSampleApp1 = activities.get(0);
mSampleApp2 = activities.get(1);
mSampleApp3 = activities.get(2);
// Disable app tracker
AppLaunchTracker.INSTANCE.initializeForTesting(new AppLaunchTracker());
PredictionUiStateManager.INSTANCE.initializeForTesting(null);
mCallback = PredictionUiStateManager.INSTANCE.get(mTargetContext).appPredictorCallback(
Client.HOME);
mDevice.setOrientationNatural();
}
@After
public void tearDown() throws Throwable {
AppLaunchTracker.INSTANCE.initializeForTesting(null);
PredictionUiStateManager.INSTANCE.initializeForTesting(null);
mDevice.unfreezeRotation();
}
/**
* Test that prediction UI is updated as soon as we get predictions from the system
*/
@Test
public void testPredictionExistsInAllApps() {
mActivityMonitor.startLauncher();
mLauncher.pressHome().switchToAllApps();
// Dispatch an update
sendPredictionUpdate(mSampleApp1, mSampleApp2);
// The first update should apply immediately.
waitForLauncherCondition("Predictions were not updated in loading state",
launcher -> getPredictedApp(launcher).size() == 2);
}
/**
* Test that prediction update is deferred if it is already visible
*/
@Test
public void testPredictionsDeferredUntilHome() {
mActivityMonitor.startLauncher();
sendPredictionUpdate(mSampleApp1, mSampleApp2);
mLauncher.pressHome().switchToAllApps();
waitForLauncherCondition("Predictions were not updated in loading state",
launcher -> getPredictedApp(launcher).size() == 2);
// Update predictions while all-apps is visible
sendPredictionUpdate(mSampleApp1, mSampleApp2, mSampleApp3);
assertEquals(2, getFromLauncher(this::getPredictedApp).size());
// Go home and go back to all-apps
mLauncher.pressHome().switchToAllApps();
assertEquals(3, getFromLauncher(this::getPredictedApp).size());
}
@Test
public void testPredictionsDisabled() {
mActivityMonitor.startLauncher();
sendPredictionUpdate();
mLauncher.pressHome().switchToAllApps();
waitForLauncherCondition("Predictions were not updated in loading state",
launcher -> launcher.getAppsView().getFloatingHeaderView()
.findFixedRowByType(PredictionRowView.class).getVisibility() == View.GONE);
assertFalse(PredictionUiStateManager.INSTANCE.get(mTargetContext)
.getCurrentState().isEnabled);
}
public ArrayList<BubbleTextView> getPredictedApp(Launcher launcher) {
PredictionRowView container = launcher.getAppsView().getFloatingHeaderView()
.findFixedRowByType(PredictionRowView.class);
ArrayList<BubbleTextView> predictedAppViews = new ArrayList<>();
for (int i = 0; i < container.getChildCount(); i++) {
View view = container.getChildAt(i);
if (view instanceof BubbleTextView && view.getVisibility() == View.VISIBLE) {
predictedAppViews.add((BubbleTextView) view);
}
}
return predictedAppViews;
}
private void sendPredictionUpdate(LauncherActivityInfo... activities) {
getOnUiThread(() -> {
List<AppTarget> targets = new ArrayList<>(activities.length);
for (LauncherActivityInfo info : activities) {
ComponentName cn = info.getComponentName();
AppTarget target = new AppTarget.Builder(
new AppTargetId("app:" + cn), cn.getPackageName(), info.getUser())
.setClassName(cn.getClassName())
.build();
targets.add(target);
}
mCallback.onTargetsAvailable(targets);
return null;
});
}
}