blob: 1702ca4b2d53a92e87d26e902cfcd5723c49075b [file] [log] [blame]
/*
* Copyright (C) 2016 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.server.pm;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertExpectException;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.list;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.parceled;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.set;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import android.Manifest.permission;
import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ShortcutInfo;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Icon;
import android.os.PersistableBundle;
import android.os.UserHandle;
import android.test.MoreAsserts;
import android.test.suitebuilder.annotation.SmallTest;
import com.android.frameworks.servicestests.R;
import com.android.server.SystemService;
/**
* Tests for ShortcutService and ShortcutManager.
*
m FrameworksServicesTests &&
adb install \
-r -g ${ANDROID_PRODUCT_OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk &&
adb shell am instrument -e class com.android.server.pm.ShortcutManagerTest2 \
-w com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
*/
@SmallTest
public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
// ShortcutInfo tests
public void testShortcutInfoMissingMandatoryFields() {
assertExpectException(
IllegalArgumentException.class,
"ID must be provided",
() -> new ShortcutInfo.Builder(getTestContext()).build());
assertExpectException(
NullPointerException.class,
"Intent action must be set",
() -> new ShortcutInfo.Builder(getTestContext()).setIntent(new Intent()));
assertExpectException(
NullPointerException.class,
"activity must be provided",
() -> new ShortcutInfo.Builder(getTestContext()).setId("id").build()
.enforceMandatoryFields());
assertExpectException(
IllegalArgumentException.class,
"title must be provided",
() -> new ShortcutInfo.Builder(getTestContext()).setId("id")
.setActivity(
new ComponentName(getTestContext().getPackageName(), "s"))
.build()
.enforceMandatoryFields());
assertExpectException(
NullPointerException.class,
"Intent must be provided",
() -> new ShortcutInfo.Builder(getTestContext()).setId("id")
.setActivity(
new ComponentName(getTestContext().getPackageName(), "s"))
.setTitle("x").build()
.enforceMandatoryFields());
}
public void testShortcutInfoParcel() {
setCaller(CALLING_PACKAGE_1, USER_10);
ShortcutInfo si = parceled(new ShortcutInfo.Builder(mClientContext)
.setId("id")
.setTitle("title")
.setIntent(makeIntent("action", ShortcutActivity.class))
.build());
assertEquals(mClientContext.getPackageName(), si.getPackage());
assertEquals(USER_10, si.getUserId());
assertEquals(HANDLE_USER_10, si.getUserHandle());
assertEquals("id", si.getId());
assertEquals("title", si.getTitle());
assertEquals("action", si.getIntent().getAction());
PersistableBundle pb = new PersistableBundle();
pb.putInt("k", 1);
si = new ShortcutInfo.Builder(getTestContext())
.setId("id")
.setActivity(new ComponentName("a", "b"))
.setIcon(Icon.createWithResource(mClientContext, 123))
.setTitle("title")
.setText("text")
.setDisabledMessage("dismes")
.setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
.setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"))
.setRank(123)
.setExtras(pb)
.build();
si.addFlags(ShortcutInfo.FLAG_PINNED);
si.setBitmapPath("abc");
si.setIconResourceId(456);
si = parceled(si);
assertEquals(getTestContext().getPackageName(), si.getPackage());
assertEquals("id", si.getId());
assertEquals(new ComponentName("a", "b"), si.getActivity());
assertEquals(123, si.getIcon().getResId());
assertEquals("title", si.getTitle());
assertEquals("text", si.getText());
assertEquals("dismes", si.getDisabledMessage());
assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories());
assertEquals("action", si.getIntent().getAction());
assertEquals("val", si.getIntent().getStringExtra("key"));
assertEquals(123, si.getRank());
assertEquals(1, si.getExtras().getInt("k"));
assertEquals(ShortcutInfo.FLAG_PINNED, si.getFlags());
assertEquals("abc", si.getBitmapPath());
assertEquals(456, si.getIconResourceId());
}
public void testShortcutInfoParcel_resId() {
setCaller(CALLING_PACKAGE_1, USER_10);
ShortcutInfo si;
PersistableBundle pb = new PersistableBundle();
pb.putInt("k", 1);
si = new ShortcutInfo.Builder(getTestContext())
.setId("id")
.setActivity(new ComponentName("a", "b"))
.setIcon(Icon.createWithResource(mClientContext, 123))
.setTitleResId(10)
.setTextResId(11)
.setDisabledMessageResId(12)
.setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
.setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"))
.setRank(123)
.setExtras(pb)
.build();
si.addFlags(ShortcutInfo.FLAG_PINNED);
si.setBitmapPath("abc");
si.setIconResourceId(456);
si = parceled(si);
assertEquals(getTestContext().getPackageName(), si.getPackage());
assertEquals("id", si.getId());
assertEquals(new ComponentName("a", "b"), si.getActivity());
assertEquals(123, si.getIcon().getResId());
assertEquals(10, si.getTitleResId());
assertEquals(11, si.getTextResId());
assertEquals(12, si.getDisabledMessageResourceId());
assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories());
assertEquals("action", si.getIntent().getAction());
assertEquals("val", si.getIntent().getStringExtra("key"));
assertEquals(123, si.getRank());
assertEquals(1, si.getExtras().getInt("k"));
assertEquals(ShortcutInfo.FLAG_PINNED, si.getFlags());
assertEquals("abc", si.getBitmapPath());
assertEquals(456, si.getIconResourceId());
}
public void testShortcutInfoClone() {
setCaller(CALLING_PACKAGE_1, USER_11);
PersistableBundle pb = new PersistableBundle();
pb.putInt("k", 1);
ShortcutInfo sorig = new ShortcutInfo.Builder(mClientContext)
.setId("id")
.setActivity(new ComponentName("a", "b"))
.setIcon(Icon.createWithResource(mClientContext, 123))
.setTitle("title")
.setText("text")
.setDisabledMessage("dismes")
.setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"))
.setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
.setRank(123)
.setExtras(pb)
.build();
sorig.addFlags(ShortcutInfo.FLAG_PINNED);
sorig.setBitmapPath("abc");
sorig.setIconResourceId(456);
ShortcutInfo si = sorig.clone(/* clone flags*/ 0);
assertEquals(USER_11, si.getUserId());
assertEquals(HANDLE_USER_11, si.getUserHandle());
assertEquals(mClientContext.getPackageName(), si.getPackage());
assertEquals("id", si.getId());
assertEquals(new ComponentName("a", "b"), si.getActivity());
assertEquals(123, si.getIcon().getResId());
assertEquals("title", si.getTitle());
assertEquals("text", si.getText());
assertEquals("dismes", si.getDisabledMessage());
assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories());
assertEquals("action", si.getIntent().getAction());
assertEquals("val", si.getIntent().getStringExtra("key"));
assertEquals(123, si.getRank());
assertEquals(1, si.getExtras().getInt("k"));
assertEquals(ShortcutInfo.FLAG_PINNED, si.getFlags());
assertEquals("abc", si.getBitmapPath());
assertEquals(456, si.getIconResourceId());
si = sorig.clone(ShortcutInfo.CLONE_REMOVE_FOR_CREATOR);
assertEquals(mClientContext.getPackageName(), si.getPackage());
assertEquals("id", si.getId());
assertEquals(new ComponentName("a", "b"), si.getActivity());
assertEquals(null, si.getIcon());
assertEquals("title", si.getTitle());
assertEquals("text", si.getText());
assertEquals("dismes", si.getDisabledMessage());
assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories());
assertEquals("action", si.getIntent().getAction());
assertEquals("val", si.getIntent().getStringExtra("key"));
assertEquals(123, si.getRank());
assertEquals(1, si.getExtras().getInt("k"));
assertEquals(ShortcutInfo.FLAG_PINNED, si.getFlags());
assertEquals(null, si.getBitmapPath());
assertEquals(456, si.getIconResourceId());
si = sorig.clone(ShortcutInfo.CLONE_REMOVE_FOR_LAUNCHER);
assertEquals(mClientContext.getPackageName(), si.getPackage());
assertEquals("id", si.getId());
assertEquals(new ComponentName("a", "b"), si.getActivity());
assertEquals(null, si.getIcon());
assertEquals("title", si.getTitle());
assertEquals("text", si.getText());
assertEquals("dismes", si.getDisabledMessage());
assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories());
assertEquals(null, si.getIntent());
assertEquals(123, si.getRank());
assertEquals(1, si.getExtras().getInt("k"));
assertEquals(ShortcutInfo.FLAG_PINNED, si.getFlags());
assertEquals(null, si.getBitmapPath());
assertEquals(456, si.getIconResourceId());
si = sorig.clone(ShortcutInfo.CLONE_REMOVE_NON_KEY_INFO);
assertEquals(mClientContext.getPackageName(), si.getPackage());
assertEquals("id", si.getId());
assertEquals(null, si.getActivity());
assertEquals(null, si.getIcon());
assertEquals(null, si.getTitle());
assertEquals(null, si.getText());
assertEquals(null, si.getDisabledMessage());
assertEquals(null, si.getCategories());
assertEquals(null, si.getIntent());
assertEquals(0, si.getRank());
assertEquals(null, si.getExtras());
assertEquals(ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_KEY_FIELDS_ONLY, si.getFlags());
assertEquals(null, si.getBitmapPath());
assertEquals(456, si.getIconResourceId());
}
public void testShortcutInfoClone_resId() {
setCaller(CALLING_PACKAGE_1, USER_11);
PersistableBundle pb = new PersistableBundle();
pb.putInt("k", 1);
ShortcutInfo sorig = new ShortcutInfo.Builder(mClientContext)
.setId("id")
.setActivity(new ComponentName("a", "b"))
.setIcon(Icon.createWithResource(mClientContext, 123))
.setTitleResId(10)
.setTextResId(11)
.setDisabledMessageResId(12)
.setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"))
.setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
.setRank(123)
.setExtras(pb)
.build();
sorig.addFlags(ShortcutInfo.FLAG_PINNED);
sorig.setBitmapPath("abc");
sorig.setIconResourceId(456);
ShortcutInfo si = sorig.clone(/* clone flags*/ 0);
assertEquals(USER_11, si.getUserId());
assertEquals(HANDLE_USER_11, si.getUserHandle());
assertEquals(mClientContext.getPackageName(), si.getPackage());
assertEquals("id", si.getId());
assertEquals(new ComponentName("a", "b"), si.getActivity());
assertEquals(123, si.getIcon().getResId());
assertEquals(10, si.getTitleResId());
assertEquals(11, si.getTextResId());
assertEquals(12, si.getDisabledMessageResourceId());
assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories());
assertEquals("action", si.getIntent().getAction());
assertEquals("val", si.getIntent().getStringExtra("key"));
assertEquals(123, si.getRank());
assertEquals(1, si.getExtras().getInt("k"));
assertEquals(ShortcutInfo.FLAG_PINNED, si.getFlags());
assertEquals("abc", si.getBitmapPath());
assertEquals(456, si.getIconResourceId());
si = sorig.clone(ShortcutInfo.CLONE_REMOVE_FOR_CREATOR);
assertEquals(mClientContext.getPackageName(), si.getPackage());
assertEquals("id", si.getId());
assertEquals(new ComponentName("a", "b"), si.getActivity());
assertEquals(null, si.getIcon());
assertEquals(10, si.getTitleResId());
assertEquals(11, si.getTextResId());
assertEquals(12, si.getDisabledMessageResourceId());
assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories());
assertEquals("action", si.getIntent().getAction());
assertEquals("val", si.getIntent().getStringExtra("key"));
assertEquals(123, si.getRank());
assertEquals(1, si.getExtras().getInt("k"));
assertEquals(ShortcutInfo.FLAG_PINNED, si.getFlags());
assertEquals(null, si.getBitmapPath());
assertEquals(456, si.getIconResourceId());
si = sorig.clone(ShortcutInfo.CLONE_REMOVE_FOR_LAUNCHER);
assertEquals(mClientContext.getPackageName(), si.getPackage());
assertEquals("id", si.getId());
assertEquals(new ComponentName("a", "b"), si.getActivity());
assertEquals(null, si.getIcon());
assertEquals(10, si.getTitleResId());
assertEquals(11, si.getTextResId());
assertEquals(12, si.getDisabledMessageResourceId());
assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories());
assertEquals(null, si.getIntent());
assertEquals(123, si.getRank());
assertEquals(1, si.getExtras().getInt("k"));
assertEquals(ShortcutInfo.FLAG_PINNED, si.getFlags());
assertEquals(null, si.getBitmapPath());
assertEquals(456, si.getIconResourceId());
si = sorig.clone(ShortcutInfo.CLONE_REMOVE_NON_KEY_INFO);
assertEquals(mClientContext.getPackageName(), si.getPackage());
assertEquals("id", si.getId());
assertEquals(null, si.getActivity());
assertEquals(null, si.getIcon());
assertEquals(0, si.getTitleResId());
assertEquals(0, si.getTextResId());
assertEquals(0, si.getDisabledMessageResourceId());
assertEquals(null, si.getCategories());
assertEquals(null, si.getIntent());
assertEquals(0, si.getRank());
assertEquals(null, si.getExtras());
assertEquals(ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_KEY_FIELDS_ONLY, si.getFlags());
assertEquals(null, si.getBitmapPath());
assertEquals(456, si.getIconResourceId());
}
public void testShortcutInfoClone_minimum() {
PersistableBundle pb = new PersistableBundle();
pb.putInt("k", 1);
ShortcutInfo sorig = new ShortcutInfo.Builder(getTestContext())
.setId("id")
.setTitle("title")
.setIntent(makeIntent("action", ShortcutActivity.class))
.build();
ShortcutInfo si = sorig.clone(/* clone flags*/ 0);
assertEquals(getTestContext().getPackageName(), si.getPackage());
assertEquals("id", si.getId());
assertEquals("title", si.getTitle());
assertEquals("action", si.getIntent().getAction());
assertEquals(null, si.getCategories());
si = sorig.clone(ShortcutInfo.CLONE_REMOVE_FOR_CREATOR);
assertEquals(getTestContext().getPackageName(), si.getPackage());
assertEquals("id", si.getId());
assertEquals("title", si.getTitle());
assertEquals("action", si.getIntent().getAction());
assertEquals(null, si.getCategories());
si = sorig.clone(ShortcutInfo.CLONE_REMOVE_FOR_LAUNCHER);
assertEquals(getTestContext().getPackageName(), si.getPackage());
assertEquals("id", si.getId());
assertEquals("title", si.getTitle());
assertEquals(null, si.getIntent());
assertEquals(null, si.getCategories());
si = sorig.clone(ShortcutInfo.CLONE_REMOVE_NON_KEY_INFO);
assertEquals(getTestContext().getPackageName(), si.getPackage());
assertEquals("id", si.getId());
assertEquals(null, si.getTitle());
assertEquals(null, si.getIntent());
assertEquals(null, si.getCategories());
}
public void testShortcutInfoCopyNonNullFieldsFrom() throws InterruptedException {
PersistableBundle pb = new PersistableBundle();
pb.putInt("k", 1);
ShortcutInfo sorig = new ShortcutInfo.Builder(getTestContext())
.setId("id")
.setActivity(new ComponentName("a", "b"))
.setIcon(Icon.createWithResource(mClientContext, 123))
.setTitle("title")
.setText("text")
.setDisabledMessage("dismes")
.setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"))
.setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
.setRank(123)
.setExtras(pb)
.build();
sorig.addFlags(ShortcutInfo.FLAG_PINNED);
sorig.setBitmapPath("abc");
sorig.setIconResourceId(456);
ShortcutInfo si;
si = sorig.clone(/* flags=*/ 0);
si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
.setActivity(new ComponentName("x", "y")).build());
assertEquals("text", si.getText());
assertEquals(new ComponentName("x", "y"), si.getActivity());
si = sorig.clone(/* flags=*/ 0);
si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
.setIcon(Icon.createWithResource(mClientContext, 456)).build());
assertEquals("text", si.getText());
assertEquals(456, si.getIcon().getResId());
si = sorig.clone(/* flags=*/ 0);
si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
.setTitle("xyz").build());
assertEquals("text", si.getText());
assertEquals("xyz", si.getTitle());
assertEquals(0, si.getTitleResId());
si = sorig.clone(/* flags=*/ 0);
si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
.setTitleResId(123).build());
assertEquals("text", si.getText());
assertEquals(null, si.getTitle());
assertEquals(123, si.getTitleResId());
si = sorig.clone(/* flags=*/ 0);
si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
.setText("xxx").build());
assertEquals(123, si.getRank());
assertEquals("xxx", si.getText());
assertEquals(0, si.getTextResId());
si = sorig.clone(/* flags=*/ 0);
si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
.setTextResId(1111).build());
assertEquals(123, si.getRank());
assertEquals(null, si.getText());
assertEquals(1111, si.getTextResId());
si = sorig.clone(/* flags=*/ 0);
si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
.setDisabledMessage("xxx").build());
assertEquals(123, si.getRank());
assertEquals("xxx", si.getDisabledMessage());
assertEquals(0, si.getDisabledMessageResourceId());
si = sorig.clone(/* flags=*/ 0);
si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
.setDisabledMessageResId(11111).build());
assertEquals(123, si.getRank());
assertEquals(null, si.getDisabledMessage());
assertEquals(11111, si.getDisabledMessageResourceId());
si = sorig.clone(/* flags=*/ 0);
si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
.setCategories(set()).build());
assertEquals("text", si.getText());
assertEquals(set(), si.getCategories());
si = sorig.clone(/* flags=*/ 0);
si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
.setCategories(set("x")).build());
assertEquals("text", si.getText());
assertEquals(set("x"), si.getCategories());
si = sorig.clone(/* flags=*/ 0);
si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
.setIntent(makeIntent("action2", ShortcutActivity.class)).build());
assertEquals("text", si.getText());
assertEquals("action2", si.getIntent().getAction());
assertEquals(null, si.getIntent().getStringExtra("key"));
si = sorig.clone(/* flags=*/ 0);
si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
.setIntent(makeIntent("action3", ShortcutActivity.class, "key", "x")).build());
assertEquals("text", si.getText());
assertEquals("action3", si.getIntent().getAction());
assertEquals("x", si.getIntent().getStringExtra("key"));
si = sorig.clone(/* flags=*/ 0);
si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
.setRank(999).build());
assertEquals("text", si.getText());
assertEquals(999, si.getRank());
PersistableBundle pb2 = new PersistableBundle();
pb2.putInt("x", 99);
si = sorig.clone(/* flags=*/ 0);
si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
.setExtras(pb2).build());
assertEquals("text", si.getText());
assertEquals(99, si.getExtras().getInt("x"));
// Make sure the timestamp gets updated too.
final long timestamp = si.getLastChangedTimestamp();
Thread.sleep(2);
si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
.setTitle("xyz").build());
assertTrue(si.getLastChangedTimestamp() > timestamp);
}
public void testShortcutInfoCopyNonNullFieldsFrom_resId() throws InterruptedException {
PersistableBundle pb = new PersistableBundle();
pb.putInt("k", 1);
ShortcutInfo sorig = new ShortcutInfo.Builder(getTestContext())
.setId("id")
.setActivity(new ComponentName("a", "b"))
.setIcon(Icon.createWithResource(mClientContext, 123))
.setTitleResId(10)
.setTextResId(11)
.setDisabledMessageResId(12)
.setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"))
.setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
.setRank(123)
.setExtras(pb)
.build();
sorig.addFlags(ShortcutInfo.FLAG_PINNED);
sorig.setBitmapPath("abc");
sorig.setIconResourceId(456);
ShortcutInfo si;
si = sorig.clone(/* flags=*/ 0);
si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
.setActivity(new ComponentName("x", "y")).build());
assertEquals(11, si.getTextResId());
assertEquals(new ComponentName("x", "y"), si.getActivity());
si = sorig.clone(/* flags=*/ 0);
si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
.setIcon(Icon.createWithResource(mClientContext, 456)).build());
assertEquals(11, si.getTextResId());
assertEquals(456, si.getIcon().getResId());
si = sorig.clone(/* flags=*/ 0);
si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
.setTitle("xyz").build());
assertEquals(11, si.getTextResId());
assertEquals("xyz", si.getTitle());
assertEquals(0, si.getTitleResId());
si = sorig.clone(/* flags=*/ 0);
si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
.setTitleResId(123).build());
assertEquals(11, si.getTextResId());
assertEquals(null, si.getTitle());
assertEquals(123, si.getTitleResId());
si = sorig.clone(/* flags=*/ 0);
si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
.setText("xxx").build());
assertEquals(123, si.getRank());
assertEquals("xxx", si.getText());
assertEquals(0, si.getTextResId());
si = sorig.clone(/* flags=*/ 0);
si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
.setTextResId(1111).build());
assertEquals(123, si.getRank());
assertEquals(null, si.getText());
assertEquals(1111, si.getTextResId());
si = sorig.clone(/* flags=*/ 0);
si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
.setDisabledMessage("xxx").build());
assertEquals(123, si.getRank());
assertEquals("xxx", si.getDisabledMessage());
assertEquals(0, si.getDisabledMessageResourceId());
si = sorig.clone(/* flags=*/ 0);
si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
.setDisabledMessageResId(11111).build());
assertEquals(123, si.getRank());
assertEquals(null, si.getDisabledMessage());
assertEquals(11111, si.getDisabledMessageResourceId());
si = sorig.clone(/* flags=*/ 0);
si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
.setCategories(set()).build());
assertEquals(11, si.getTextResId());
assertEquals(set(), si.getCategories());
si = sorig.clone(/* flags=*/ 0);
si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
.setCategories(set("x")).build());
assertEquals(11, si.getTextResId());
assertEquals(set("x"), si.getCategories());
si = sorig.clone(/* flags=*/ 0);
si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
.setIntent(makeIntent("action2", ShortcutActivity.class)).build());
assertEquals(11, si.getTextResId());
assertEquals("action2", si.getIntent().getAction());
assertEquals(null, si.getIntent().getStringExtra("key"));
si = sorig.clone(/* flags=*/ 0);
si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
.setIntent(makeIntent("action3", ShortcutActivity.class, "key", "x")).build());
assertEquals(11, si.getTextResId());
assertEquals("action3", si.getIntent().getAction());
assertEquals("x", si.getIntent().getStringExtra("key"));
si = sorig.clone(/* flags=*/ 0);
si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
.setRank(999).build());
assertEquals(11, si.getTextResId());
assertEquals(999, si.getRank());
PersistableBundle pb2 = new PersistableBundle();
pb2.putInt("x", 99);
si = sorig.clone(/* flags=*/ 0);
si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
.setExtras(pb2).build());
assertEquals(11, si.getTextResId());
assertEquals(99, si.getExtras().getInt("x"));
// Make sure the timestamp gets updated too.
final long timestamp = si.getLastChangedTimestamp();
Thread.sleep(2);
si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
.setTitle("xyz").build());
assertTrue(si.getLastChangedTimestamp() > timestamp);
}
public void testShortcutInfoSaveAndLoad() throws InterruptedException {
setCaller(CALLING_PACKAGE_1, USER_10);
final Icon bmp32x32 = Icon.createWithBitmap(BitmapFactory.decodeResource(
getTestContext().getResources(), R.drawable.black_32x32));
PersistableBundle pb = new PersistableBundle();
pb.putInt("k", 1);
ShortcutInfo sorig = new ShortcutInfo.Builder(mClientContext)
.setId("id")
.setActivity(new ComponentName(mClientContext, ShortcutActivity2.class))
.setIcon(bmp32x32)
.setTitle("title")
.setText("text")
.setDisabledMessage("dismes")
.setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"))
.setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
.setRank(123)
.setExtras(pb)
.build();
mManager.addDynamicShortcuts(list(sorig));
Thread.sleep(2);
final long now = System.currentTimeMillis();
// Save and load.
mService.saveDirtyInfo();
initService();
mService.handleUnlockUser(USER_10);
ShortcutInfo si;
si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id", USER_10);
assertEquals(USER_10, si.getUserId());
assertEquals(HANDLE_USER_10, si.getUserHandle());
assertEquals(CALLING_PACKAGE_1, si.getPackage());
assertEquals("id", si.getId());
assertEquals(ShortcutActivity2.class.getName(), si.getActivity().getClassName());
assertEquals(null, si.getIcon());
assertEquals("title", si.getTitle());
assertEquals("text", si.getText());
assertEquals("dismes", si.getDisabledMessage());
assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories());
assertEquals("action", si.getIntent().getAction());
assertEquals("val", si.getIntent().getStringExtra("key"));
assertEquals(123, si.getRank());
assertEquals(1, si.getExtras().getInt("k"));
assertEquals(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_HAS_ICON_FILE, si.getFlags());
assertNotNull(si.getBitmapPath()); // Something should be set.
assertEquals(0, si.getIconResourceId());
assertTrue(si.getLastChangedTimestamp() < now);
}
public void testShortcutInfoSaveAndLoad_resId() throws InterruptedException {
setCaller(CALLING_PACKAGE_1, USER_10);
final Icon bmp32x32 = Icon.createWithBitmap(BitmapFactory.decodeResource(
getTestContext().getResources(), R.drawable.black_32x32));
PersistableBundle pb = new PersistableBundle();
pb.putInt("k", 1);
ShortcutInfo sorig = new ShortcutInfo.Builder(mClientContext)
.setId("id")
.setActivity(new ComponentName(mClientContext, ShortcutActivity2.class))
.setIcon(bmp32x32)
.setTitleResId(10)
.setTextResId(11)
.setDisabledMessageResId(12)
.setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"))
.setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
.setRank(123)
.setExtras(pb)
.build();
mManager.addDynamicShortcuts(list(sorig));
Thread.sleep(2);
final long now = System.currentTimeMillis();
// Save and load.
mService.saveDirtyInfo();
initService();
mService.handleUnlockUser(USER_10);
ShortcutInfo si;
si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id", USER_10);
assertEquals(USER_10, si.getUserId());
assertEquals(HANDLE_USER_10, si.getUserHandle());
assertEquals(CALLING_PACKAGE_1, si.getPackage());
assertEquals("id", si.getId());
assertEquals(ShortcutActivity2.class.getName(), si.getActivity().getClassName());
assertEquals(null, si.getIcon());
assertEquals(10, si.getTitleResId());
assertEquals(11, si.getTextResId());
assertEquals(12, si.getDisabledMessageResourceId());
assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories());
assertEquals("action", si.getIntent().getAction());
assertEquals("val", si.getIntent().getStringExtra("key"));
assertEquals(123, si.getRank());
assertEquals(1, si.getExtras().getInt("k"));
assertEquals(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_HAS_ICON_FILE, si.getFlags());
assertNotNull(si.getBitmapPath()); // Something should be set.
assertEquals(0, si.getIconResourceId());
assertTrue(si.getLastChangedTimestamp() < now);
}
public void testShortcutInfoSaveAndLoad_forBackup() {
setCaller(CALLING_PACKAGE_1, USER_0);
final Icon bmp32x32 = Icon.createWithBitmap(BitmapFactory.decodeResource(
getTestContext().getResources(), R.drawable.black_32x32));
PersistableBundle pb = new PersistableBundle();
pb.putInt("k", 1);
ShortcutInfo sorig = new ShortcutInfo.Builder(mClientContext)
.setId("id")
.setActivity(new ComponentName(mClientContext, ShortcutActivity2.class))
.setIcon(bmp32x32)
.setTitle("title")
.setText("text")
.setDisabledMessage("dismes")
.setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"))
.setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
.setRank(123)
.setExtras(pb)
.build();
mManager.addDynamicShortcuts(list(sorig));
// Dynamic shortcuts won't be backed up, so we need to pin it.
setCaller(LAUNCHER_1, USER_0);
mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("id"), HANDLE_USER_0);
// Do backup & restore.
backupAndRestore();
mService.handleUnlockUser(USER_0); // Load user-0.
ShortcutInfo si;
si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id", USER_0);
assertEquals(CALLING_PACKAGE_1, si.getPackage());
assertEquals("id", si.getId());
assertEquals(ShortcutActivity2.class.getName(), si.getActivity().getClassName());
assertEquals(null, si.getIcon());
assertEquals("title", si.getTitle());
assertEquals("text", si.getText());
assertEquals("dismes", si.getDisabledMessage());
assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories());
assertEquals("action", si.getIntent().getAction());
assertEquals("val", si.getIntent().getStringExtra("key"));
assertEquals(123, si.getRank());
assertEquals(1, si.getExtras().getInt("k"));
assertEquals(ShortcutInfo.FLAG_PINNED, si.getFlags());
assertNull(si.getBitmapPath()); // No icon.
assertEquals(0, si.getIconResourceId());
}
public void testShortcutInfoSaveAndLoad_forBackup_resId() {
setCaller(CALLING_PACKAGE_1, USER_0);
final Icon bmp32x32 = Icon.createWithBitmap(BitmapFactory.decodeResource(
getTestContext().getResources(), R.drawable.black_32x32));
PersistableBundle pb = new PersistableBundle();
pb.putInt("k", 1);
ShortcutInfo sorig = new ShortcutInfo.Builder(mClientContext)
.setId("id")
.setActivity(new ComponentName(mClientContext, ShortcutActivity2.class))
.setIcon(bmp32x32)
.setTitleResId(10)
.setTextResId(11)
.setDisabledMessageResId(12)
.setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"))
.setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
.setRank(123)
.setExtras(pb)
.build();
mManager.addDynamicShortcuts(list(sorig));
// Dynamic shortcuts won't be backed up, so we need to pin it.
setCaller(LAUNCHER_1, USER_0);
mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("id"), HANDLE_USER_0);
// Do backup & restore.
backupAndRestore();
mService.handleUnlockUser(USER_0); // Load user-0.
ShortcutInfo si;
si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id", USER_0);
assertEquals(CALLING_PACKAGE_1, si.getPackage());
assertEquals("id", si.getId());
assertEquals(ShortcutActivity2.class.getName(), si.getActivity().getClassName());
assertEquals(null, si.getIcon());
assertEquals(10, si.getTitleResId());
assertEquals(11, si.getTextResId());
assertEquals(12, si.getDisabledMessageResourceId());
assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories());
assertEquals("action", si.getIntent().getAction());
assertEquals("val", si.getIntent().getStringExtra("key"));
assertEquals(123, si.getRank());
assertEquals(1, si.getExtras().getInt("k"));
assertEquals(ShortcutInfo.FLAG_PINNED, si.getFlags());
assertNull(si.getBitmapPath()); // No icon.
assertEquals(0, si.getIconResourceId());
}
public void testThrottling() {
final ShortcutInfo si1 = makeShortcut("shortcut1");
assertTrue(mManager.setDynamicShortcuts(list(si1)));
assertEquals(2, mManager.getRemainingCallCount());
assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
mInjectedCurrentTimeMillis++;
assertTrue(mManager.setDynamicShortcuts(list(si1)));
assertEquals(1, mManager.getRemainingCallCount());
assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
mInjectedCurrentTimeMillis++;
assertTrue(mManager.setDynamicShortcuts(list(si1)));
assertEquals(0, mManager.getRemainingCallCount());
assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
// Reached the max
mInjectedCurrentTimeMillis++;
assertFalse(mManager.setDynamicShortcuts(list(si1)));
assertEquals(0, mManager.getRemainingCallCount());
assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
// Still throttled
mInjectedCurrentTimeMillis = START_TIME + INTERVAL - 1;
assertFalse(mManager.setDynamicShortcuts(list(si1)));
assertEquals(0, mManager.getRemainingCallCount());
assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
// Now it should work.
mInjectedCurrentTimeMillis++;
assertTrue(mManager.setDynamicShortcuts(list(si1))); // fail
assertEquals(2, mManager.getRemainingCallCount());
assertEquals(START_TIME + INTERVAL * 2, mManager.getRateLimitResetTime());
mInjectedCurrentTimeMillis++;
assertTrue(mManager.setDynamicShortcuts(list(si1)));
assertEquals(1, mManager.getRemainingCallCount());
assertEquals(START_TIME + INTERVAL * 2, mManager.getRateLimitResetTime());
mInjectedCurrentTimeMillis++;
assertTrue(mManager.setDynamicShortcuts(list(si1)));
assertEquals(0, mManager.getRemainingCallCount());
assertEquals(START_TIME + INTERVAL * 2, mManager.getRateLimitResetTime());
mInjectedCurrentTimeMillis++;
assertFalse(mManager.setDynamicShortcuts(list(si1)));
assertEquals(0, mManager.getRemainingCallCount());
assertEquals(START_TIME + INTERVAL * 2, mManager.getRateLimitResetTime());
// 4 hours later...
mInjectedCurrentTimeMillis = START_TIME + 4 * INTERVAL;
assertTrue(mManager.setDynamicShortcuts(list(si1)));
assertEquals(2, mManager.getRemainingCallCount());
assertEquals(START_TIME + INTERVAL * 5, mManager.getRateLimitResetTime());
mInjectedCurrentTimeMillis++;
assertTrue(mManager.setDynamicShortcuts(list(si1)));
assertEquals(1, mManager.getRemainingCallCount());
assertEquals(START_TIME + INTERVAL * 5, mManager.getRateLimitResetTime());
// Make sure getRemainingCallCount() itself gets reset without calling setDynamicShortcuts().
mInjectedCurrentTimeMillis = START_TIME + 8 * INTERVAL;
assertEquals(3, mManager.getRemainingCallCount());
assertEquals(START_TIME + INTERVAL * 9, mManager.getRateLimitResetTime());
mInjectedCurrentTimeMillis++;
assertTrue(mManager.setDynamicShortcuts(list(si1)));
assertEquals(2, mManager.getRemainingCallCount());
assertEquals(START_TIME + INTERVAL * 9, mManager.getRateLimitResetTime());
}
public void testThrottling_rewind() {
final ShortcutInfo si1 = makeShortcut("shortcut1");
assertTrue(mManager.setDynamicShortcuts(list(si1)));
assertEquals(2, mManager.getRemainingCallCount());
assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
mInjectedCurrentTimeMillis = 12345; // Clock reset!
// Since the clock looks invalid, the counter shouldn't have reset.
assertEquals(2, mManager.getRemainingCallCount());
assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
// Forward again. Still haven't reset yet.
mInjectedCurrentTimeMillis = START_TIME + INTERVAL - 1;
assertEquals(2, mManager.getRemainingCallCount());
assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
// Now rewind -- this will reset the counters.
mInjectedCurrentTimeMillis = START_TIME - 100000;
assertEquals(3, mManager.getRemainingCallCount());
assertTrue(mManager.setDynamicShortcuts(list(si1)));
assertEquals(2, mManager.getRemainingCallCount());
// Forward again, should be reset now.
mInjectedCurrentTimeMillis += INTERVAL;
assertEquals(3, mManager.getRemainingCallCount());
}
public void testThrottling_perPackage() {
final ShortcutInfo si1 = makeShortcut("shortcut1");
assertTrue(mManager.setDynamicShortcuts(list(si1)));
assertEquals(2, mManager.getRemainingCallCount());
mInjectedCurrentTimeMillis++;
assertTrue(mManager.setDynamicShortcuts(list(si1)));
assertEquals(1, mManager.getRemainingCallCount());
mInjectedCurrentTimeMillis++;
assertTrue(mManager.setDynamicShortcuts(list(si1)));
assertEquals(0, mManager.getRemainingCallCount());
// Reached the max
mInjectedCurrentTimeMillis++;
assertFalse(mManager.setDynamicShortcuts(list(si1)));
// Try from a different caller.
mInjectedClientPackage = CALLING_PACKAGE_2;
mInjectedCallingUid = CALLING_UID_2;
// Need to create a new one wit the updated package name.
final ShortcutInfo si2 = makeShortcut("shortcut1");
assertEquals(3, mManager.getRemainingCallCount());
assertTrue(mManager.setDynamicShortcuts(list(si2)));
assertEquals(2, mManager.getRemainingCallCount());
mInjectedCurrentTimeMillis++;
assertTrue(mManager.setDynamicShortcuts(list(si2)));
assertEquals(1, mManager.getRemainingCallCount());
// Back to the original caller, still throttled.
mInjectedClientPackage = CALLING_PACKAGE_1;
mInjectedCallingUid = CALLING_UID_1;
mInjectedCurrentTimeMillis = START_TIME + INTERVAL - 1;
assertEquals(0, mManager.getRemainingCallCount());
assertFalse(mManager.setDynamicShortcuts(list(si1)));
assertEquals(0, mManager.getRemainingCallCount());
// Now it should work.
mInjectedCurrentTimeMillis++;
assertTrue(mManager.setDynamicShortcuts(list(si1)));
mInjectedCurrentTimeMillis++;
assertTrue(mManager.setDynamicShortcuts(list(si1)));
mInjectedCurrentTimeMillis++;
assertTrue(mManager.setDynamicShortcuts(list(si1)));
mInjectedCurrentTimeMillis++;
assertFalse(mManager.setDynamicShortcuts(list(si1)));
mInjectedCurrentTimeMillis = START_TIME + 4 * INTERVAL;
assertTrue(mManager.setDynamicShortcuts(list(si1)));
assertTrue(mManager.setDynamicShortcuts(list(si1)));
assertTrue(mManager.setDynamicShortcuts(list(si1)));
assertFalse(mManager.setDynamicShortcuts(list(si1)));
mInjectedClientPackage = CALLING_PACKAGE_2;
mInjectedCallingUid = CALLING_UID_2;
assertEquals(3, mManager.getRemainingCallCount());
assertTrue(mManager.setDynamicShortcuts(list(si2)));
assertTrue(mManager.setDynamicShortcuts(list(si2)));
assertTrue(mManager.setDynamicShortcuts(list(si2)));
assertFalse(mManager.setDynamicShortcuts(list(si2)));
}
public void testThrottling_localeChanges() {
prepareCrossProfileDataSet();
dumpsysOnLogcat("Before save & load");
mService.saveDirtyInfo();
initService();
final long origSequenceNumber = mService.getLocaleChangeSequenceNumber();
// onSystemLocaleChangedNoLock before boot completed will be ignored.
mInternal.onSystemLocaleChangedNoLock();
assertEquals(origSequenceNumber, mService.getLocaleChangeSequenceNumber());
mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
mInternal.onSystemLocaleChangedNoLock();
assertEquals(origSequenceNumber + 1, mService.getLocaleChangeSequenceNumber());
// Note at this point only user-0 is loaded, and the counters are reset for this user,
// but it will work for other users too, because we persist when
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
assertEquals(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
assertEquals(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
assertEquals(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_4, USER_0, () -> {
assertEquals(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
assertEquals(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
assertEquals(3, mManager.getRemainingCallCount());
});
mService.saveDirtyInfo();
initService();
// Make sure the counter is persisted.
assertEquals(origSequenceNumber + 1, mService.getLocaleChangeSequenceNumber());
}
public void testThrottling_foreground() throws Exception {
prepareCrossProfileDataSet();
dumpsysOnLogcat("Before save & load");
mService.saveDirtyInfo();
initService();
// We need to update the current time from time to time, since some of the internal checks
// rely on the time being correctly incremented.
mInjectedCurrentTimeMillis++;
// First, all packages have less than 3 (== initial value) remaining calls.
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_4, USER_0, () -> {
MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
});
mInjectedCurrentTimeMillis++;
// State changed, but not foreground, so no resetting.
mService.mUidObserver.onUidStateChanged(
CALLING_UID_1, ActivityManager.PROCESS_STATE_TOP_SLEEPING);
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_4, USER_0, () -> {
MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
});
mInjectedCurrentTimeMillis++;
// State changed, package1 foreground, reset.
mService.mUidObserver.onUidStateChanged(
CALLING_UID_1, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
assertEquals(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_4, USER_0, () -> {
MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
});
mService.mUidObserver.onUidStateChanged(
CALLING_UID_1, ActivityManager.PROCESS_STATE_TOP_SLEEPING);
mInjectedCurrentTimeMillis++;
// Different app comes to foreground briefly, and goes back to background.
// Now, make sure package 2's counter is reset, even in this case.
mService.mUidObserver.onUidStateChanged(
CALLING_UID_2, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
mService.mUidObserver.onUidStateChanged(
CALLING_UID_2, ActivityManager.PROCESS_STATE_TOP_SLEEPING);
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
assertEquals(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
assertEquals(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_4, USER_0, () -> {
MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
});
mInjectedCurrentTimeMillis++;
// Do the same thing one more time. This would catch the bug with mixuing up
// the current time and the elapsed time.
runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
mManager.updateShortcuts(list(makeShortcut("s")));
MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
});
mService.mUidObserver.onUidStateChanged(
CALLING_UID_2, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
mService.mUidObserver.onUidStateChanged(
CALLING_UID_2, ActivityManager.PROCESS_STATE_TOP_SLEEPING);
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
assertEquals(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
assertEquals(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_4, USER_0, () -> {
MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
});
mInjectedCurrentTimeMillis++;
// Package 1 on user-10 comes to foreground.
// Now, also try calling some APIs and make sure foreground apps don't get throttled.
mService.mUidObserver.onUidStateChanged(
UserHandle.getUid(USER_10, CALLING_UID_1),
ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
assertEquals(3, mManager.getRemainingCallCount());
mManager.setDynamicShortcuts(list(makeShortcut("s")));
mManager.setDynamicShortcuts(list(makeShortcut("s")));
mManager.setDynamicShortcuts(list(makeShortcut("s")));
assertEquals(0, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
assertEquals(3, mManager.getRemainingCallCount());
mManager.setDynamicShortcuts(list(makeShortcut("s")));
mManager.setDynamicShortcuts(list(makeShortcut("s")));
mManager.setDynamicShortcuts(list(makeShortcut("s")));
assertEquals(0, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
mManager.setDynamicShortcuts(list(makeShortcut("s")));
mManager.setDynamicShortcuts(list(makeShortcut("s")));
mManager.setDynamicShortcuts(list(makeShortcut("s")));
assertEquals(0, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_4, USER_0, () -> {
MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
mManager.setDynamicShortcuts(list(makeShortcut("s")));
mManager.setDynamicShortcuts(list(makeShortcut("s")));
mManager.setDynamicShortcuts(list(makeShortcut("s")));
assertEquals(0, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
mManager.setDynamicShortcuts(list(makeShortcut("s")));
mManager.setDynamicShortcuts(list(makeShortcut("s")));
mManager.setDynamicShortcuts(list(makeShortcut("s")));
assertEquals(0, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
assertEquals(3, mManager.getRemainingCallCount());
mManager.setDynamicShortcuts(list(makeShortcut("s")));
mManager.setDynamicShortcuts(list(makeShortcut("s")));
mManager.setDynamicShortcuts(list(makeShortcut("s")));
assertEquals(3, mManager.getRemainingCallCount()); // Still 3!
});
}
public void testThrottling_resetByInternalCall() throws Exception {
prepareCrossProfileDataSet();
dumpsysOnLogcat("Before save & load");
mService.saveDirtyInfo();
initService();
// First, all packages have less than 3 (== initial value) remaining calls.
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_4, USER_0, () -> {
MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
});
// Simulate a call from sys UI.
mCallerPermissions.add(permission.RESET_SHORTCUT_MANAGER_THROTTLING);
mService.onApplicationActive(CALLING_PACKAGE_1, USER_0);
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
assertEquals(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_4, USER_0, () -> {
MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
});
mService.onApplicationActive(CALLING_PACKAGE_3, USER_0);
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
assertEquals(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
assertEquals(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_4, USER_0, () -> {
MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
});
mService.onApplicationActive(CALLING_PACKAGE_1, USER_10);
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
assertEquals(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
assertEquals(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_4, USER_0, () -> {
MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
assertEquals(3, mManager.getRemainingCallCount());
});
}
public void testReportShortcutUsed() {
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
reset(mMockUsageStatsManagerInternal);
// Report with an nonexistent shortcut.
mManager.reportShortcutUsed("s1");
verify(mMockUsageStatsManagerInternal, times(0)).reportShortcutUsage(
anyString(), anyString(), anyInt());
// Publish s2, but s1 still doesn't exist.
mManager.setDynamicShortcuts(list(makeShortcut("s2")));
mManager.reportShortcutUsed("s1");
verify(mMockUsageStatsManagerInternal, times(0)).reportShortcutUsage(
anyString(), anyString(), anyInt());
mManager.reportShortcutUsed("s2");
verify(mMockUsageStatsManagerInternal, times(1)).reportShortcutUsage(
eq(CALLING_PACKAGE_1), eq("s2"), eq(USER_10));
});
runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
// Try with a different package.
reset(mMockUsageStatsManagerInternal);
// Report with an nonexistent shortcut.
mManager.reportShortcutUsed("s2");
verify(mMockUsageStatsManagerInternal, times(0)).reportShortcutUsage(
anyString(), anyString(), anyInt());
// Publish s2, but s1 still doesn't exist.
mManager.setDynamicShortcuts(list(makeShortcut("s3")));
mManager.reportShortcutUsed("s2");
verify(mMockUsageStatsManagerInternal, times(0)).reportShortcutUsage(
anyString(), anyString(), anyInt());
mManager.reportShortcutUsed("s3");
verify(mMockUsageStatsManagerInternal, times(1)).reportShortcutUsage(
eq(CALLING_PACKAGE_2), eq("s3"), eq(USER_10));
});
}
}