Merge changes from topic "fix-package-manager-usages"
* changes: Fix usages of PackageManager APIs in Telephony Fix hidden API usage in PackageChangeReceiver
This commit is contained in:
@@ -24,17 +24,17 @@ import android.content.Intent;
|
|||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
import android.os.HandlerThread;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
|
|
||||||
import com.android.internal.os.BackgroundThread;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper class for monitoring the state of packages: adding, removing,
|
* Helper class for monitoring the state of packages: adding, removing,
|
||||||
* updating, and disappearing and reappearing on the SD card.
|
* updating, and disappearing and reappearing on the SD card.
|
||||||
*/
|
*/
|
||||||
public abstract class PackageChangeReceiver extends BroadcastReceiver {
|
public abstract class PackageChangeReceiver extends BroadcastReceiver {
|
||||||
static final IntentFilter sPackageIntentFilter = new IntentFilter();
|
static final IntentFilter sPackageIntentFilter = new IntentFilter();
|
||||||
|
private static HandlerThread sHandlerThread;
|
||||||
static {
|
static {
|
||||||
sPackageIntentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
|
sPackageIntentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
|
||||||
sPackageIntentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
|
sPackageIntentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
|
||||||
@@ -43,28 +43,24 @@ public abstract class PackageChangeReceiver extends BroadcastReceiver {
|
|||||||
sPackageIntentFilter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
|
sPackageIntentFilter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
|
||||||
sPackageIntentFilter.addDataScheme("package");
|
sPackageIntentFilter.addDataScheme("package");
|
||||||
}
|
}
|
||||||
|
// Keep an instance of Context around as long as we still want the receiver:
|
||||||
|
// if the instance of Context gets garbage-collected, it'll unregister the receiver, so only
|
||||||
|
// unset when we want to unregister.
|
||||||
Context mRegisteredContext;
|
Context mRegisteredContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* To register the intents that needed for monitoring the state of packages
|
* To register the intents that needed for monitoring the state of packages. Once this method
|
||||||
|
* has been called on an instance of {@link PackageChangeReceiver}, all subsequent calls must
|
||||||
|
* have the same {@code user} argument.
|
||||||
*/
|
*/
|
||||||
public void register(@NonNull Context context, @Nullable Looper thread,
|
public void register(@NonNull Context context, @Nullable Looper thread,
|
||||||
@Nullable UserHandle user) {
|
@Nullable UserHandle user) {
|
||||||
if (mRegisteredContext != null) {
|
if (mRegisteredContext != null) {
|
||||||
throw new IllegalStateException("Already registered");
|
throw new IllegalStateException("Already registered");
|
||||||
}
|
}
|
||||||
Handler handler = (thread == null) ? BackgroundThread.getHandler() : new Handler(thread);
|
Handler handler = new Handler(thread == null ? getStaticLooper() : thread);
|
||||||
mRegisteredContext = context;
|
mRegisteredContext = user == null ? context : context.createContextAsUser(user, 0);
|
||||||
if (handler != null) {
|
mRegisteredContext.registerReceiver(this, sPackageIntentFilter, null, handler);
|
||||||
if (user != null) {
|
|
||||||
context.registerReceiverAsUser(this, user, sPackageIntentFilter, null, handler);
|
|
||||||
} else {
|
|
||||||
context.registerReceiver(this, sPackageIntentFilter,
|
|
||||||
null, handler);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw new NullPointerException();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -78,6 +74,14 @@ public abstract class PackageChangeReceiver extends BroadcastReceiver {
|
|||||||
mRegisteredContext = null;
|
mRegisteredContext = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static synchronized Looper getStaticLooper() {
|
||||||
|
if (sHandlerThread == null) {
|
||||||
|
sHandlerThread = new HandlerThread(PackageChangeReceiver.class.getSimpleName());
|
||||||
|
sHandlerThread.start();
|
||||||
|
}
|
||||||
|
return sHandlerThread.getLooper();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is invoked when receive the Intent.ACTION_PACKAGE_ADDED
|
* This method is invoked when receive the Intent.ACTION_PACKAGE_ADDED
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ import java.util.concurrent.ExecutionException;
|
|||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -250,6 +250,7 @@ public final class SmsApplication {
|
|||||||
private static Collection<SmsApplicationData> getApplicationCollectionInternal(
|
private static Collection<SmsApplicationData> getApplicationCollectionInternal(
|
||||||
Context context, int userId) {
|
Context context, int userId) {
|
||||||
PackageManager packageManager = context.getPackageManager();
|
PackageManager packageManager = context.getPackageManager();
|
||||||
|
UserHandle userHandle = UserHandle.of(userId);
|
||||||
|
|
||||||
// Get the list of apps registered for SMS
|
// Get the list of apps registered for SMS
|
||||||
Intent intent = new Intent(Intents.SMS_DELIVER_ACTION);
|
Intent intent = new Intent(Intents.SMS_DELIVER_ACTION);
|
||||||
@@ -258,7 +259,7 @@ public final class SmsApplication {
|
|||||||
}
|
}
|
||||||
List<ResolveInfo> smsReceivers = packageManager.queryBroadcastReceiversAsUser(intent,
|
List<ResolveInfo> smsReceivers = packageManager.queryBroadcastReceiversAsUser(intent,
|
||||||
PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
|
PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
|
||||||
userId);
|
userHandle);
|
||||||
|
|
||||||
HashMap<String, SmsApplicationData> receivers = new HashMap<String, SmsApplicationData>();
|
HashMap<String, SmsApplicationData> receivers = new HashMap<String, SmsApplicationData>();
|
||||||
|
|
||||||
@@ -285,7 +286,7 @@ public final class SmsApplication {
|
|||||||
intent.setDataAndType(null, "application/vnd.wap.mms-message");
|
intent.setDataAndType(null, "application/vnd.wap.mms-message");
|
||||||
List<ResolveInfo> mmsReceivers = packageManager.queryBroadcastReceiversAsUser(intent,
|
List<ResolveInfo> mmsReceivers = packageManager.queryBroadcastReceiversAsUser(intent,
|
||||||
PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
|
PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
|
||||||
userId);
|
userHandle);
|
||||||
for (ResolveInfo resolveInfo : mmsReceivers) {
|
for (ResolveInfo resolveInfo : mmsReceivers) {
|
||||||
final ActivityInfo activityInfo = resolveInfo.activityInfo;
|
final ActivityInfo activityInfo = resolveInfo.activityInfo;
|
||||||
if (activityInfo == null) {
|
if (activityInfo == null) {
|
||||||
@@ -327,7 +328,7 @@ public final class SmsApplication {
|
|||||||
Uri.fromParts(SCHEME_SMSTO, "", null));
|
Uri.fromParts(SCHEME_SMSTO, "", null));
|
||||||
List<ResolveInfo> sendToActivities = packageManager.queryIntentActivitiesAsUser(intent,
|
List<ResolveInfo> sendToActivities = packageManager.queryIntentActivitiesAsUser(intent,
|
||||||
PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
|
PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
|
||||||
userId);
|
userHandle);
|
||||||
for (ResolveInfo resolveInfo : sendToActivities) {
|
for (ResolveInfo resolveInfo : sendToActivities) {
|
||||||
final ActivityInfo activityInfo = resolveInfo.activityInfo;
|
final ActivityInfo activityInfo = resolveInfo.activityInfo;
|
||||||
if (activityInfo == null) {
|
if (activityInfo == null) {
|
||||||
@@ -345,7 +346,7 @@ public final class SmsApplication {
|
|||||||
List<ResolveInfo> smsAppChangedReceivers =
|
List<ResolveInfo> smsAppChangedReceivers =
|
||||||
packageManager.queryBroadcastReceiversAsUser(intent,
|
packageManager.queryBroadcastReceiversAsUser(intent,
|
||||||
PackageManager.MATCH_DIRECT_BOOT_AWARE
|
PackageManager.MATCH_DIRECT_BOOT_AWARE
|
||||||
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId);
|
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userHandle);
|
||||||
if (DEBUG_MULTIUSER) {
|
if (DEBUG_MULTIUSER) {
|
||||||
Log.i(LOG_TAG, "getApplicationCollectionInternal smsAppChangedActivities=" +
|
Log.i(LOG_TAG, "getApplicationCollectionInternal smsAppChangedActivities=" +
|
||||||
smsAppChangedReceivers);
|
smsAppChangedReceivers);
|
||||||
@@ -372,7 +373,7 @@ public final class SmsApplication {
|
|||||||
List<ResolveInfo> providerChangedReceivers =
|
List<ResolveInfo> providerChangedReceivers =
|
||||||
packageManager.queryBroadcastReceiversAsUser(intent,
|
packageManager.queryBroadcastReceiversAsUser(intent,
|
||||||
PackageManager.MATCH_DIRECT_BOOT_AWARE
|
PackageManager.MATCH_DIRECT_BOOT_AWARE
|
||||||
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId);
|
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userHandle);
|
||||||
if (DEBUG_MULTIUSER) {
|
if (DEBUG_MULTIUSER) {
|
||||||
Log.i(LOG_TAG, "getApplicationCollectionInternal providerChangedActivities=" +
|
Log.i(LOG_TAG, "getApplicationCollectionInternal providerChangedActivities=" +
|
||||||
providerChangedReceivers);
|
providerChangedReceivers);
|
||||||
@@ -399,7 +400,7 @@ public final class SmsApplication {
|
|||||||
List<ResolveInfo> simFullReceivers =
|
List<ResolveInfo> simFullReceivers =
|
||||||
packageManager.queryBroadcastReceiversAsUser(intent,
|
packageManager.queryBroadcastReceiversAsUser(intent,
|
||||||
PackageManager.MATCH_DIRECT_BOOT_AWARE
|
PackageManager.MATCH_DIRECT_BOOT_AWARE
|
||||||
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId);
|
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userHandle);
|
||||||
if (DEBUG_MULTIUSER) {
|
if (DEBUG_MULTIUSER) {
|
||||||
Log.i(LOG_TAG, "getApplicationCollectionInternal simFullReceivers="
|
Log.i(LOG_TAG, "getApplicationCollectionInternal simFullReceivers="
|
||||||
+ simFullReceivers);
|
+ simFullReceivers);
|
||||||
@@ -631,7 +632,8 @@ public final class SmsApplication {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// We only make the change if the new package is valid
|
// We only make the change if the new package is valid
|
||||||
PackageManager packageManager = context.getPackageManager();
|
PackageManager packageManager =
|
||||||
|
context.createContextAsUser(userHandle, 0).getPackageManager();
|
||||||
Collection<SmsApplicationData> applications = getApplicationCollectionInternal(
|
Collection<SmsApplicationData> applications = getApplicationCollectionInternal(
|
||||||
context, userId);
|
context, userId);
|
||||||
SmsApplicationData oldAppData = oldPackageName != null ?
|
SmsApplicationData oldAppData = oldPackageName != null ?
|
||||||
@@ -642,8 +644,7 @@ public final class SmsApplication {
|
|||||||
AppOpsManager appOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
|
AppOpsManager appOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
|
||||||
if (oldPackageName != null) {
|
if (oldPackageName != null) {
|
||||||
try {
|
try {
|
||||||
int uid = packageManager.getPackageInfoAsUser(
|
int uid = packageManager.getPackageInfo(oldPackageName, 0).applicationInfo.uid;
|
||||||
oldPackageName, 0, userId).applicationInfo.uid;
|
|
||||||
setExclusiveAppops(oldPackageName, appOps, uid, AppOpsManager.MODE_DEFAULT);
|
setExclusiveAppops(oldPackageName, appOps, uid, AppOpsManager.MODE_DEFAULT);
|
||||||
} catch (NameNotFoundException e) {
|
} catch (NameNotFoundException e) {
|
||||||
Rlog.w(LOG_TAG, "Old SMS package not found: " + oldPackageName);
|
Rlog.w(LOG_TAG, "Old SMS package not found: " + oldPackageName);
|
||||||
@@ -807,9 +808,16 @@ public final class SmsApplication {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void onPackageChanged() {
|
private void onPackageChanged() {
|
||||||
PackageManager packageManager = mContext.getPackageManager();
|
int userId;
|
||||||
|
try {
|
||||||
|
userId = getSendingUser().getIdentifier();
|
||||||
|
} catch (NullPointerException e) {
|
||||||
|
// This should never happen in prod -- unit tests will put the receiver into a
|
||||||
|
// unusual state where the pending result is null, which produces a NPE when calling
|
||||||
|
// getSendingUserId. Just pretend like it's the system user for testing.
|
||||||
|
userId = UserHandle.USER_SYSTEM;
|
||||||
|
}
|
||||||
Context userContext = mContext;
|
Context userContext = mContext;
|
||||||
final int userId = getSendingUserId();
|
|
||||||
if (userId != UserHandle.USER_SYSTEM) {
|
if (userId != UserHandle.USER_SYSTEM) {
|
||||||
try {
|
try {
|
||||||
userContext = mContext.createPackageContextAsUser(mContext.getPackageName(), 0,
|
userContext = mContext.createPackageContextAsUser(mContext.getPackageName(), 0,
|
||||||
@@ -820,10 +828,11 @@ public final class SmsApplication {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
PackageManager packageManager = userContext.getPackageManager();
|
||||||
// Ensure this component is still configured as the preferred activity
|
// Ensure this component is still configured as the preferred activity
|
||||||
ComponentName componentName = getDefaultSendToApplication(userContext, true);
|
ComponentName componentName = getDefaultSendToApplication(userContext, true);
|
||||||
if (componentName != null) {
|
if (componentName != null) {
|
||||||
configurePreferredActivity(packageManager, componentName, userId);
|
configurePreferredActivity(packageManager, componentName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -835,41 +844,36 @@ public final class SmsApplication {
|
|||||||
|
|
||||||
@UnsupportedAppUsage
|
@UnsupportedAppUsage
|
||||||
private static void configurePreferredActivity(PackageManager packageManager,
|
private static void configurePreferredActivity(PackageManager packageManager,
|
||||||
ComponentName componentName, int userId) {
|
ComponentName componentName) {
|
||||||
// Add the four activity preferences we want to direct to this app.
|
// Add the four activity preferences we want to direct to this app.
|
||||||
replacePreferredActivity(packageManager, componentName, userId, SCHEME_SMS);
|
replacePreferredActivity(packageManager, componentName, SCHEME_SMS);
|
||||||
replacePreferredActivity(packageManager, componentName, userId, SCHEME_SMSTO);
|
replacePreferredActivity(packageManager, componentName, SCHEME_SMSTO);
|
||||||
replacePreferredActivity(packageManager, componentName, userId, SCHEME_MMS);
|
replacePreferredActivity(packageManager, componentName, SCHEME_MMS);
|
||||||
replacePreferredActivity(packageManager, componentName, userId, SCHEME_MMSTO);
|
replacePreferredActivity(packageManager, componentName, SCHEME_MMSTO);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the ACTION_SENDTO activity to the specified component for the specified scheme.
|
* Updates the ACTION_SENDTO activity to the specified component for the specified scheme.
|
||||||
*/
|
*/
|
||||||
private static void replacePreferredActivity(PackageManager packageManager,
|
private static void replacePreferredActivity(PackageManager packageManager,
|
||||||
ComponentName componentName, int userId, String scheme) {
|
ComponentName componentName, String scheme) {
|
||||||
// Build the set of existing activities that handle this scheme
|
// Build the set of existing activities that handle this scheme
|
||||||
Intent intent = new Intent(Intent.ACTION_SENDTO, Uri.fromParts(scheme, "", null));
|
Intent intent = new Intent(Intent.ACTION_SENDTO, Uri.fromParts(scheme, "", null));
|
||||||
List<ResolveInfo> resolveInfoList = packageManager.queryIntentActivitiesAsUser(
|
List<ResolveInfo> resolveInfoList = packageManager.queryIntentActivities(
|
||||||
intent, PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_RESOLVED_FILTER,
|
intent, PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_RESOLVED_FILTER);
|
||||||
userId);
|
|
||||||
|
|
||||||
// Build the set of ComponentNames for these activities
|
List<ComponentName> components = resolveInfoList.stream().map(info ->
|
||||||
final int n = resolveInfoList.size();
|
new ComponentName(info.activityInfo.packageName, info.activityInfo.name))
|
||||||
ComponentName[] set = new ComponentName[n];
|
.collect(Collectors.toList());
|
||||||
for (int i = 0; i < n; i++) {
|
|
||||||
ResolveInfo info = resolveInfoList.get(i);
|
|
||||||
set[i] = new ComponentName(info.activityInfo.packageName, info.activityInfo.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the preferred SENDTO activity for the specified scheme
|
// Update the preferred SENDTO activity for the specified scheme
|
||||||
IntentFilter intentFilter = new IntentFilter();
|
IntentFilter intentFilter = new IntentFilter();
|
||||||
intentFilter.addAction(Intent.ACTION_SENDTO);
|
intentFilter.addAction(Intent.ACTION_SENDTO);
|
||||||
intentFilter.addCategory(Intent.CATEGORY_DEFAULT);
|
intentFilter.addCategory(Intent.CATEGORY_DEFAULT);
|
||||||
intentFilter.addDataScheme(scheme);
|
intentFilter.addDataScheme(scheme);
|
||||||
packageManager.replacePreferredActivityAsUser(intentFilter,
|
packageManager.replacePreferredActivity(intentFilter,
|
||||||
IntentFilter.MATCH_CATEGORY_SCHEME + IntentFilter.MATCH_ADJUSTMENT_NORMAL,
|
IntentFilter.MATCH_CATEGORY_SCHEME + IntentFilter.MATCH_ADJUSTMENT_NORMAL,
|
||||||
set, componentName, userId);
|
components, componentName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1 +1,3 @@
|
|||||||
rule com.android.internal.telephony.SmsApplication* com.android.internal.telephony.tests.SmsApplication@1
|
rule com.android.internal.telephony.SmsApplication* com.android.internal.telephony.tests.SmsApplication@1
|
||||||
|
rule android.telephony.PackageChangeReceiver* com.android.internal.telephony.tests.PackageChangeReceiver@1
|
||||||
|
rule com.android.internal.os.BackgroundThread* com.android.internal.telephony.tests.BackgroundThread@1
|
||||||
|
|||||||
@@ -17,26 +17,34 @@
|
|||||||
package com.android.internal.telephony.tests;
|
package com.android.internal.telephony.tests;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.mockito.ArgumentMatchers.anyInt;
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
|
import static org.mockito.ArgumentMatchers.isNotNull;
|
||||||
|
import static org.mockito.ArgumentMatchers.isNull;
|
||||||
import static org.mockito.ArgumentMatchers.nullable;
|
import static org.mockito.ArgumentMatchers.nullable;
|
||||||
import static org.mockito.Mockito.atLeastOnce;
|
import static org.mockito.Mockito.atLeastOnce;
|
||||||
import static org.mockito.Mockito.doAnswer;
|
import static org.mockito.Mockito.doAnswer;
|
||||||
|
import static org.mockito.Mockito.times;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import android.Manifest;
|
import android.Manifest;
|
||||||
import android.app.AppOpsManager;
|
import android.app.AppOpsManager;
|
||||||
import android.app.role.RoleManager;
|
import android.app.role.RoleManager;
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.IntentFilter;
|
||||||
import android.content.pm.ActivityInfo;
|
import android.content.pm.ActivityInfo;
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.content.pm.PackageInfo;
|
import android.content.pm.PackageInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.pm.ResolveInfo;
|
import android.content.pm.ResolveInfo;
|
||||||
import android.content.pm.ServiceInfo;
|
import android.content.pm.ServiceInfo;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Handler;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.provider.Telephony;
|
import android.provider.Telephony;
|
||||||
import android.telephony.TelephonyManager;
|
import android.telephony.TelephonyManager;
|
||||||
@@ -48,11 +56,15 @@ import com.android.internal.telephony.SmsApplication;
|
|||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.MockitoAnnotations;
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unit tests for the {@link SmsApplication} utility class
|
* Unit tests for the {@link SmsApplication} utility class
|
||||||
@@ -80,6 +92,13 @@ public class SmsApplicationTest {
|
|||||||
AppOpsManager.OPSTR_READ_CELL_BROADCASTS
|
AppOpsManager.OPSTR_READ_CELL_BROADCASTS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private static final Set<String> SCHEMES_FOR_PREFERRED_APP = Arrays.stream(new String[]{
|
||||||
|
"mms",
|
||||||
|
"mmsto",
|
||||||
|
"sms",
|
||||||
|
"smsto"
|
||||||
|
}).collect(Collectors.toSet());
|
||||||
|
|
||||||
@Mock private Context mContext;
|
@Mock private Context mContext;
|
||||||
@Mock private TelephonyManager mTelephonyManager;
|
@Mock private TelephonyManager mTelephonyManager;
|
||||||
@Mock private RoleManager mRoleManager;
|
@Mock private RoleManager mRoleManager;
|
||||||
@@ -94,13 +113,16 @@ public class SmsApplicationTest {
|
|||||||
when(mContext.getPackageManager()).thenReturn(mPackageManager);
|
when(mContext.getPackageManager()).thenReturn(mPackageManager);
|
||||||
when(mContext.getSystemService(RoleManager.class)).thenReturn(mRoleManager);
|
when(mContext.getSystemService(RoleManager.class)).thenReturn(mRoleManager);
|
||||||
when(mContext.getSystemService(AppOpsManager.class)).thenReturn(mAppOpsManager);
|
when(mContext.getSystemService(AppOpsManager.class)).thenReturn(mAppOpsManager);
|
||||||
|
when(mContext.createContextAsUser(isNotNull(), anyInt())).thenReturn(mContext);
|
||||||
|
|
||||||
doAnswer(invocation -> getResolveInfosForIntent(invocation.getArgument(0)))
|
doAnswer(invocation -> getResolveInfosForIntent(invocation.getArgument(0)))
|
||||||
.when(mPackageManager)
|
.when(mPackageManager)
|
||||||
.queryBroadcastReceiversAsUser(nullable(Intent.class), anyInt(), anyInt());
|
.queryBroadcastReceiversAsUser(nullable(Intent.class), anyInt(),
|
||||||
|
nullable(UserHandle.class));
|
||||||
doAnswer(invocation -> getResolveInfosForIntent(invocation.getArgument(0)))
|
doAnswer(invocation -> getResolveInfosForIntent(invocation.getArgument(0)))
|
||||||
.when(mPackageManager)
|
.when(mPackageManager)
|
||||||
.queryIntentActivitiesAsUser(nullable(Intent.class), anyInt(), anyInt());
|
.queryIntentActivitiesAsUser(nullable(Intent.class), anyInt(),
|
||||||
|
nullable(UserHandle.class));
|
||||||
doAnswer(invocation -> getResolveInfosForIntent(invocation.getArgument(0)))
|
doAnswer(invocation -> getResolveInfosForIntent(invocation.getArgument(0)))
|
||||||
.when(mPackageManager)
|
.when(mPackageManager)
|
||||||
.queryIntentServicesAsUser(nullable(Intent.class), anyInt(),
|
.queryIntentServicesAsUser(nullable(Intent.class), anyInt(),
|
||||||
@@ -137,6 +159,37 @@ public class SmsApplicationTest {
|
|||||||
AppOpsManager.MODE_ALLOWED);
|
AppOpsManager.MODE_ALLOWED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPackageChanged() throws Exception {
|
||||||
|
setupPackageInfosForCoreApps();
|
||||||
|
SmsApplication.initSmsPackageMonitor(mContext);
|
||||||
|
verify(mContext).createContextAsUser(eq(UserHandle.ALL), anyInt());
|
||||||
|
ArgumentCaptor<BroadcastReceiver> captor = ArgumentCaptor.forClass(BroadcastReceiver.class);
|
||||||
|
verify(mContext).registerReceiver(captor.capture(), isNotNull(),
|
||||||
|
isNull(), nullable(Handler.class));
|
||||||
|
BroadcastReceiver smsPackageMonitor = captor.getValue();
|
||||||
|
|
||||||
|
Intent packageChangedIntent = new Intent(Intent.ACTION_PACKAGE_CHANGED);
|
||||||
|
packageChangedIntent.setData(
|
||||||
|
Uri.fromParts("package", TEST_COMPONENT_NAME.getPackageName(), null));
|
||||||
|
smsPackageMonitor.onReceive(mContext, packageChangedIntent);
|
||||||
|
|
||||||
|
ArgumentCaptor<IntentFilter> intentFilterCaptor =
|
||||||
|
ArgumentCaptor.forClass(IntentFilter.class);
|
||||||
|
verify(mPackageManager, times(SCHEMES_FOR_PREFERRED_APP.size()))
|
||||||
|
.replacePreferredActivity(intentFilterCaptor.capture(),
|
||||||
|
eq(IntentFilter.MATCH_CATEGORY_SCHEME
|
||||||
|
| IntentFilter.MATCH_ADJUSTMENT_NORMAL),
|
||||||
|
isNotNull(List.class),
|
||||||
|
eq(new ComponentName(TEST_COMPONENT_NAME.getPackageName(), SEND_TO_NAME)));
|
||||||
|
|
||||||
|
Set<String> capturedSchemes = intentFilterCaptor.getAllValues().stream()
|
||||||
|
.map(intentFilter -> intentFilter.getDataScheme(0))
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
assertEquals(SCHEMES_FOR_PREFERRED_APP.size(), capturedSchemes.size());
|
||||||
|
assertTrue(SCHEMES_FOR_PREFERRED_APP.containsAll(capturedSchemes));
|
||||||
|
}
|
||||||
|
|
||||||
private void setupPackageInfosForCoreApps() throws Exception {
|
private void setupPackageInfosForCoreApps() throws Exception {
|
||||||
PackageInfo phonePackageInfo = new PackageInfo();
|
PackageInfo phonePackageInfo = new PackageInfo();
|
||||||
ApplicationInfo phoneApplicationInfo = new ApplicationInfo();
|
ApplicationInfo phoneApplicationInfo = new ApplicationInfo();
|
||||||
|
|||||||
Reference in New Issue
Block a user