Move user/package intent reception out of PermissionMonitor
This is a no-op refactoring that moves the reception of
package and user-related intents in PermissionMonitor to
BroadcastReceiveHelper.
It then dispatches these events to the PermissionMonitor.
This change is necessary to centralize intent receivers
from other subclasses to ConnectivityService in
subsequent modifications.
This reverts the design change introduced in aosp/2183343, which
had PermissionMonitor listening to user change events instead
of ConnectivityService.
Flag: EXEMPT refactor
Test: atest ConnectivityCoverageTests:android.net.connectivity.com.android.server.connectivity.PermissionMonitorTest \
ConnectivityCoverageTests:android.net.connectivity.com.android.server.ConnectivityServiceTest \
ConnectivityCoverageTests:android.net.connectivity.com.android.server.connectivity.BroadcastReceiveHelperTest \
--update-device
Bug: 410731080
Change-Id: Ic79afc18a6e8603ddf8d48a1f78cf8d98f2447ae
This commit is contained in:
parent
ff4adce964
commit
8b1fe1976b
5 changed files with 584 additions and 204 deletions
|
|
@ -362,6 +362,7 @@ import com.android.server.connectivity.ApplicationSelfCertifiedNetworkCapabiliti
|
|||
import com.android.server.connectivity.AutodestructReference;
|
||||
import com.android.server.connectivity.AutomaticOnOffKeepaliveTracker;
|
||||
import com.android.server.connectivity.AutomaticOnOffKeepaliveTracker.AutomaticOnOffKeepalive;
|
||||
import com.android.server.connectivity.BroadcastReceiveHelper;
|
||||
import com.android.server.connectivity.CarrierPrivilegeAuthenticator;
|
||||
import com.android.server.connectivity.ClatCoordinator;
|
||||
import com.android.server.connectivity.ConnectivityFlags;
|
||||
|
|
@ -439,7 +440,8 @@ import java.util.function.Predicate;
|
|||
* @hide
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.S)
|
||||
public class ConnectivityService extends IConnectivityManager.Stub {
|
||||
public class ConnectivityService extends IConnectivityManager.Stub
|
||||
implements BroadcastReceiveHelper.Delegate {
|
||||
private static final String TAG = ConnectivityService.class.getSimpleName();
|
||||
|
||||
private static final String DIAG_ARG = "--diag";
|
||||
|
|
@ -528,6 +530,8 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||
|
||||
private final PermissionMonitor mPermissionMonitor;
|
||||
|
||||
private final BroadcastReceiveHelper mBroadcastReceiveHelper;
|
||||
|
||||
@VisibleForTesting
|
||||
final RequestInfoPerUidCounter mNetworkRequestCounter;
|
||||
@VisibleForTesting
|
||||
|
|
@ -1942,6 +1946,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||
mTrackerHandler = new NetworkStateTrackerHandler(mHandlerThread.getLooper());
|
||||
mConnectivityDiagnosticsHandler =
|
||||
new ConnectivityDiagnosticsHandler(mHandlerThread.getLooper());
|
||||
mBroadcastReceiveHelper = new BroadcastReceiveHelper(mContext, mHandler, this);
|
||||
|
||||
mReleasePendingIntentDelayMs = Settings.Secure.getInt(context.getContentResolver(),
|
||||
ConnectivitySettingsManager.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS, 5_000);
|
||||
|
|
@ -2009,22 +2014,8 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||
mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
|
||||
|
||||
mUserAllContext = mContext.createContextAsUser(UserHandle.ALL, 0 /* flags */);
|
||||
// Listen for user add/removes to inform PermissionMonitor.
|
||||
// Should run on mHandler to avoid any races.
|
||||
final IntentFilter userIntentFilter = new IntentFilter();
|
||||
userIntentFilter.addAction(Intent.ACTION_USER_ADDED);
|
||||
userIntentFilter.addAction(Intent.ACTION_USER_REMOVED);
|
||||
mUserAllContext.registerReceiver(mUserIntentReceiver, userIntentFilter,
|
||||
null /* broadcastPermission */, mHandler);
|
||||
|
||||
// Listen to package add/removes for netd
|
||||
final IntentFilter packageIntentFilter = new IntentFilter();
|
||||
packageIntentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
|
||||
packageIntentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
|
||||
packageIntentFilter.addAction(Intent.ACTION_PACKAGE_REPLACED);
|
||||
packageIntentFilter.addDataScheme("package");
|
||||
mUserAllContext.registerReceiver(mPackageIntentReceiver, packageIntentFilter,
|
||||
null /* broadcastPermission */, mHandler);
|
||||
// TODO: Move all intent receivers to the helper class.
|
||||
mBroadcastReceiveHelper.registerReceivers();
|
||||
|
||||
// This is needed for pre-V devices to propagate the data saver status
|
||||
// to the BPF map. This isn't supported before Android T because BPF maps are
|
||||
|
|
@ -7720,14 +7711,17 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||
}
|
||||
}
|
||||
|
||||
private void onUserAdded(@NonNull final UserHandle user) {
|
||||
@Override
|
||||
public void onUserAdded(@NonNull final UserHandle user) {
|
||||
if (mOemNetworkPreferences.getNetworkPreferences().size() > 0) {
|
||||
handleSetOemNetworkPreference(mOemNetworkPreferences, null);
|
||||
}
|
||||
updateProfileAllowedNetworks();
|
||||
mPermissionMonitor.onUserAdded(user);
|
||||
}
|
||||
|
||||
private void onUserRemoved(@NonNull final UserHandle user) {
|
||||
@Override
|
||||
public void onUserRemoved(@NonNull final UserHandle user) {
|
||||
// If there was a network preference for this user, remove it.
|
||||
handleSetProfileNetworkPreference(
|
||||
List.of(new ProfileNetworkPreferenceInfo(user, null, true,
|
||||
|
|
@ -7736,9 +7730,32 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||
if (mOemNetworkPreferences.getNetworkPreferences().size() > 0) {
|
||||
handleSetOemNetworkPreference(mOemNetworkPreferences, null);
|
||||
}
|
||||
mPermissionMonitor.onUserRemoved(user);
|
||||
}
|
||||
|
||||
private void onPackageChanged(@NonNull final String packageName) {
|
||||
@Override
|
||||
public void onPackageAdded(@NonNull final String packageName, final int uid) {
|
||||
handlePackageChanged(packageName);
|
||||
mPermissionMonitor.onPackageAdded(packageName, uid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPackageRemoved(@NonNull final String packageName, final int uid) {
|
||||
handlePackageChanged(packageName);
|
||||
mPermissionMonitor.onPackageRemoved(packageName, uid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPackageReplaced(@NonNull final String packageName, final int uid) {
|
||||
handlePackageChanged(packageName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onExternalApplicationsAvailable(@Nullable String[] pkgList) {
|
||||
mPermissionMonitor.onExternalApplicationsAvailable(pkgList);
|
||||
}
|
||||
|
||||
private void handlePackageChanged(@NonNull final String packageName) {
|
||||
// This is necessary in case a package is added or removed, but also when it's replaced to
|
||||
// run as a new UID by its manifest rules. Also, if a separate package shares the same UID
|
||||
// as one in the preferences, then it should follow the same routing as that other package,
|
||||
|
|
@ -7754,45 +7771,6 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||
}
|
||||
}
|
||||
|
||||
private final BroadcastReceiver mUserIntentReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
ensureRunningOnConnectivityServiceThread();
|
||||
final String action = intent.getAction();
|
||||
final UserHandle user = intent.getParcelableExtra(Intent.EXTRA_USER);
|
||||
|
||||
// User should be filled for below intents, check the existence.
|
||||
if (user == null) {
|
||||
Log.wtf(TAG, intent.getAction() + " broadcast without EXTRA_USER");
|
||||
return;
|
||||
}
|
||||
|
||||
if (Intent.ACTION_USER_ADDED.equals(action)) {
|
||||
onUserAdded(user);
|
||||
} else if (Intent.ACTION_USER_REMOVED.equals(action)) {
|
||||
onUserRemoved(user);
|
||||
} else {
|
||||
Log.wtf(TAG, "received unexpected intent: " + action);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final BroadcastReceiver mPackageIntentReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
ensureRunningOnConnectivityServiceThread();
|
||||
switch (intent.getAction()) {
|
||||
case Intent.ACTION_PACKAGE_ADDED:
|
||||
case Intent.ACTION_PACKAGE_REMOVED:
|
||||
case Intent.ACTION_PACKAGE_REPLACED:
|
||||
onPackageChanged(intent.getData().getSchemeSpecificPart());
|
||||
break;
|
||||
default:
|
||||
Log.wtf(TAG, "received unexpected intent: " + intent.getAction());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
||||
private final BroadcastReceiver mDataSaverReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -0,0 +1,230 @@
|
|||
/*
|
||||
* Copyright (C) 2025 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.connectivity;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.UserHandle;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.net.module.util.HandlerUtils;
|
||||
|
||||
/**
|
||||
* Helper class for ConnectivityService to listen for broadcast intents and
|
||||
* provide callbacks on a given {@link HandlerThread}.
|
||||
*/
|
||||
public class BroadcastReceiveHelper {
|
||||
private static final String TAG = BroadcastReceiveHelper.class.getSimpleName();
|
||||
private final Context mContext;
|
||||
private final Handler mHandler;
|
||||
private final Delegate mCallback;
|
||||
|
||||
/**
|
||||
* Interface defining the callback methods for package and user related events.
|
||||
*/
|
||||
public interface Delegate {
|
||||
/**
|
||||
* Called when a new package has been installed.
|
||||
*
|
||||
* @param packageName The name of the package that was added.
|
||||
* @param uid The user ID of the application that was added.
|
||||
*/
|
||||
void onPackageAdded(String packageName, int uid);
|
||||
|
||||
/**
|
||||
* Called when a package has been uninstalled.
|
||||
*
|
||||
* @param packageName The name of the package that was removed.
|
||||
* @param uid The user ID of the application that was removed.
|
||||
*/
|
||||
void onPackageRemoved(String packageName, int uid);
|
||||
|
||||
/**
|
||||
* Called when an existing package has been replaced with a new version.
|
||||
*
|
||||
* @param packageName The name of the package that was replaced.
|
||||
* @param uid The user ID of the application that was replaced.
|
||||
*/
|
||||
void onPackageReplaced(String packageName, int uid);
|
||||
|
||||
/**
|
||||
* Called when the availability of external applications changes.
|
||||
*
|
||||
* @param pkgList An array of package names that have become available.
|
||||
*/
|
||||
void onExternalApplicationsAvailable(String[] pkgList);
|
||||
|
||||
/**
|
||||
* Called when a new user has been added to the device.
|
||||
*
|
||||
* @param userHandle The {@link UserHandle} of the user that was added.
|
||||
*/
|
||||
void onUserAdded(UserHandle userHandle);
|
||||
|
||||
/**
|
||||
* Called when a user has been removed from the device.
|
||||
*
|
||||
* @param userHandle The {@link UserHandle} of the user that was removed.
|
||||
*/
|
||||
void onUserRemoved(UserHandle userHandle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code ConnectivityBroadcastReceiveHelper}.
|
||||
*
|
||||
* @param context The {@link Context} to register the broadcast receiver.
|
||||
* @param handler The handler where the callback methods will be executed.
|
||||
* @param callback The {@link Delegate} implementation that will receive the broadcast events.
|
||||
*/
|
||||
public BroadcastReceiveHelper(@NonNull Context context,
|
||||
@NonNull final Handler handler, @NonNull Delegate callback) {
|
||||
this.mContext = context;
|
||||
this.mHandler = handler;
|
||||
this.mCallback = callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the broadcast receivers for package and user related intents.
|
||||
* The callbacks for these events will be executed on the {@link HandlerThread}
|
||||
* provided in the constructor.
|
||||
*/
|
||||
public void registerReceivers() {
|
||||
final Context userAllContext = mContext.createContextAsUser(UserHandle.ALL, 0 /* flags */);
|
||||
|
||||
// Listen to user events.
|
||||
// TODO: Receive intents inline and post them to the handler.
|
||||
final IntentFilter userIntentFilter = new IntentFilter();
|
||||
userIntentFilter.addAction(Intent.ACTION_USER_ADDED);
|
||||
userIntentFilter.addAction(Intent.ACTION_USER_REMOVED);
|
||||
userAllContext.registerReceiver(mUserIntentReceiver, userIntentFilter,
|
||||
null /* broadcastPermission */, mHandler);
|
||||
|
||||
// Listen to package change events.
|
||||
final IntentFilter packageIntentFilter = new IntentFilter();
|
||||
packageIntentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
|
||||
packageIntentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
|
||||
packageIntentFilter.addAction(Intent.ACTION_PACKAGE_REPLACED);
|
||||
packageIntentFilter.addDataScheme("package");
|
||||
userAllContext.registerReceiver(mPackageIntentReceiver, packageIntentFilter,
|
||||
null /* broadcastPermission */, mHandler);
|
||||
|
||||
// For PermissionMonitor, listen to EXTERNAL_APPLICATIONS_AVAILABLE is that an app
|
||||
// becoming available means it may need to gain a permission. But an app that becomes
|
||||
// unavailable can neither gain nor lose permissions on that account, it just can no
|
||||
// longer run. Thus, doesn't need to listen to EXTERNAL_APPLICATIONS_UNAVAILABLE.
|
||||
final IntentFilter externalIntentFilter =
|
||||
new IntentFilter(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
|
||||
userAllContext.registerReceiver(mExternalAppIntentReceiver, externalIntentFilter,
|
||||
null /* broadcastPermission */, mHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters the broadcast receiver, stopping the listener from receiving further events.
|
||||
* It's important to call this method when the listener is no longer needed to avoid
|
||||
* potential resource leaks.
|
||||
*/
|
||||
public void unregisterReceivers() {
|
||||
try {
|
||||
mContext.unregisterReceiver(mPackageIntentReceiver);
|
||||
mContext.unregisterReceiver(mUserIntentReceiver);
|
||||
mContext.unregisterReceiver(mExternalAppIntentReceiver);
|
||||
} catch (IllegalArgumentException e) {
|
||||
// Receiver was not registered
|
||||
}
|
||||
}
|
||||
|
||||
private final BroadcastReceiver mPackageIntentReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
HandlerUtils.ensureRunningOnHandlerThread(mHandler);
|
||||
|
||||
final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
|
||||
final Uri packageData = intent.getData();
|
||||
// AOSP never sends null data in the intent (see
|
||||
// BroadcastHelper#sendPostInstallBroadcasts)
|
||||
// but OEMs may have modified this code.
|
||||
if (packageData == null) {
|
||||
Log.wtf(TAG, "Intent received with null data: " + intent);
|
||||
return;
|
||||
}
|
||||
final String packageName = packageData.getSchemeSpecificPart();
|
||||
|
||||
switch (intent.getAction()) {
|
||||
case Intent.ACTION_PACKAGE_ADDED: {
|
||||
mCallback.onPackageAdded(packageName, uid);
|
||||
break;
|
||||
}
|
||||
case Intent.ACTION_PACKAGE_REMOVED: {
|
||||
mCallback.onPackageRemoved(packageName, uid);
|
||||
break;
|
||||
}
|
||||
case Intent.ACTION_PACKAGE_REPLACED: {
|
||||
mCallback.onPackageReplaced(packageName, uid);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
Log.wtf(TAG, "received unexpected intent: " + intent.getAction());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final BroadcastReceiver mExternalAppIntentReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
HandlerUtils.ensureRunningOnHandlerThread(mHandler);
|
||||
switch (intent.getAction()) {
|
||||
case Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE: {
|
||||
final String[] pkgList =
|
||||
intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
|
||||
mCallback.onExternalApplicationsAvailable(pkgList);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
Log.wtf(TAG, "received unexpected intent: " + intent.getAction());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final BroadcastReceiver mUserIntentReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
HandlerUtils.ensureRunningOnHandlerThread(mHandler);
|
||||
final String action = intent.getAction();
|
||||
final UserHandle user = intent.getParcelableExtra(Intent.EXTRA_USER);
|
||||
|
||||
// User should be filled for below intents, check the existence.
|
||||
if (user == null) {
|
||||
Log.wtf(TAG, intent.getAction() + " broadcast without EXTRA_USER");
|
||||
return;
|
||||
}
|
||||
|
||||
if (Intent.ACTION_USER_ADDED.equals(action)) {
|
||||
mCallback.onUserAdded(user);
|
||||
} else if (Intent.ACTION_USER_REMOVED.equals(action)) {
|
||||
mCallback.onUserRemoved(user);
|
||||
} else {
|
||||
Log.wtf(TAG, "received unexpected intent: " + action);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -42,10 +42,7 @@ import android.annotation.NonNull;
|
|||
import android.annotation.Nullable;
|
||||
import android.app.compat.CompatChanges;
|
||||
import android.content.AttributionSource;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
|
|
@ -164,49 +161,6 @@ public class PermissionMonitor {
|
|||
private static final int MAX_PERMISSION_UPDATE_LOGS = 40;
|
||||
private final SharedLog mPermissionUpdateLogs = new SharedLog(MAX_PERMISSION_UPDATE_LOGS, TAG);
|
||||
|
||||
private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
final String action = intent.getAction();
|
||||
|
||||
if (Intent.ACTION_PACKAGE_ADDED.equals(action)) {
|
||||
final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
|
||||
final Uri packageData = intent.getData();
|
||||
final String packageName =
|
||||
packageData != null ? packageData.getSchemeSpecificPart() : null;
|
||||
onPackageAdded(packageName, uid);
|
||||
} else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
|
||||
final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
|
||||
final Uri packageData = intent.getData();
|
||||
final String packageName =
|
||||
packageData != null ? packageData.getSchemeSpecificPart() : null;
|
||||
onPackageRemoved(packageName, uid);
|
||||
} else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)) {
|
||||
final String[] pkgList =
|
||||
intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
|
||||
onExternalApplicationsAvailable(pkgList);
|
||||
} else if (Intent.ACTION_USER_ADDED.equals(action)) {
|
||||
final UserHandle user = intent.getParcelableExtra(Intent.EXTRA_USER);
|
||||
// User should be filled for below intents, check the existence.
|
||||
if (user == null) {
|
||||
Log.wtf(TAG, action + " broadcast without EXTRA_USER");
|
||||
return;
|
||||
}
|
||||
onUserAdded(user);
|
||||
} else if (Intent.ACTION_USER_REMOVED.equals(action)) {
|
||||
final UserHandle user = intent.getParcelableExtra(Intent.EXTRA_USER);
|
||||
// User should be filled for below intents, check the existence.
|
||||
if (user == null) {
|
||||
Log.wtf(TAG, action + " broadcast without EXTRA_USER");
|
||||
return;
|
||||
}
|
||||
onUserRemoved(user);
|
||||
} else {
|
||||
Log.wtf(TAG, "received unexpected intent: " + action);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Dependencies of PermissionMonitor, for injection in tests.
|
||||
*/
|
||||
|
|
@ -462,28 +416,6 @@ public class PermissionMonitor {
|
|||
|
||||
final Handler handler = new Handler(mThread.getLooper());
|
||||
final Context userAllContext = mContext.createContextAsUser(UserHandle.ALL, 0 /* flags */);
|
||||
final IntentFilter intentFilter = new IntentFilter();
|
||||
intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
|
||||
intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
|
||||
intentFilter.addDataScheme("package");
|
||||
userAllContext.registerReceiver(
|
||||
mIntentReceiver, intentFilter, null /* broadcastPermission */, handler);
|
||||
|
||||
// Listen to EXTERNAL_APPLICATIONS_AVAILABLE is that an app becoming available means it may
|
||||
// need to gain a permission. But an app that becomes unavailable can neither gain nor lose
|
||||
// permissions on that account, it just can no longer run. Thus, doesn't need to listen to
|
||||
// EXTERNAL_APPLICATIONS_UNAVAILABLE.
|
||||
final IntentFilter externalIntentFilter =
|
||||
new IntentFilter(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
|
||||
userAllContext.registerReceiver(
|
||||
mIntentReceiver, externalIntentFilter, null /* broadcastPermission */, handler);
|
||||
|
||||
// Listen for user add/remove.
|
||||
final IntentFilter userIntentFilter = new IntentFilter();
|
||||
userIntentFilter.addAction(Intent.ACTION_USER_ADDED);
|
||||
userIntentFilter.addAction(Intent.ACTION_USER_REMOVED);
|
||||
userAllContext.registerReceiver(
|
||||
mIntentReceiver, userIntentFilter, null /* broadcastPermission */, handler);
|
||||
|
||||
// Register UIDS_ALLOWED_ON_RESTRICTED_NETWORKS setting observer
|
||||
mDeps.registerContentObserver(
|
||||
|
|
@ -625,8 +557,8 @@ public class PermissionMonitor {
|
|||
*
|
||||
* @hide
|
||||
*/
|
||||
@VisibleForTesting
|
||||
synchronized void onUserAdded(@NonNull UserHandle user) {
|
||||
public synchronized void onUserAdded(@NonNull UserHandle user) {
|
||||
ensureRunningOnHandlerThread();
|
||||
mUsers.add(user);
|
||||
|
||||
final List<PackageInfo> apps = getInstalledPackagesAsUser(user);
|
||||
|
|
@ -657,8 +589,8 @@ public class PermissionMonitor {
|
|||
*
|
||||
* @hide
|
||||
*/
|
||||
@VisibleForTesting
|
||||
synchronized void onUserRemoved(@NonNull UserHandle user) {
|
||||
public synchronized void onUserRemoved(@NonNull UserHandle user) {
|
||||
ensureRunningOnHandlerThread();
|
||||
mUsers.remove(user);
|
||||
|
||||
// Remove uids network permissions that belongs to the user.
|
||||
|
|
@ -843,8 +775,8 @@ public class PermissionMonitor {
|
|||
*
|
||||
* @hide
|
||||
*/
|
||||
@VisibleForTesting
|
||||
synchronized void onPackageAdded(@NonNull final String packageName, final int uid) {
|
||||
public synchronized void onPackageAdded(@NonNull final String packageName, final int uid) {
|
||||
ensureRunningOnHandlerThread();
|
||||
// Update uid permission.
|
||||
updateAppIdTrafficPermission(uid);
|
||||
// Get the appId permission from all users then send the latest permission to netd.
|
||||
|
|
@ -908,8 +840,8 @@ public class PermissionMonitor {
|
|||
*
|
||||
* @hide
|
||||
*/
|
||||
@VisibleForTesting
|
||||
synchronized void onPackageRemoved(@NonNull final String packageName, final int uid) {
|
||||
public synchronized void onPackageRemoved(@NonNull final String packageName, final int uid) {
|
||||
ensureRunningOnHandlerThread();
|
||||
// Update uid permission.
|
||||
updateAppIdTrafficPermission(uid);
|
||||
if (BpfNetMaps.isAtLeast25Q2()) {
|
||||
|
|
@ -1307,7 +1239,13 @@ public class PermissionMonitor {
|
|||
+ ", remove=" + removedUids);
|
||||
}
|
||||
|
||||
private synchronized void onExternalApplicationsAvailable(String[] pkgList) {
|
||||
/**
|
||||
* Called when external applications are available.
|
||||
*
|
||||
* @param pkgList The package names of the external applications.
|
||||
*/
|
||||
public synchronized void onExternalApplicationsAvailable(String[] pkgList) {
|
||||
ensureRunningOnHandlerThread();
|
||||
if (CollectionUtils.isEmpty(pkgList)) {
|
||||
Log.e(TAG, "No available external application.");
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,284 @@
|
|||
/*
|
||||
* Copyright (C) 2025 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.connectivity
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE
|
||||
import android.content.Intent.ACTION_PACKAGE_ADDED
|
||||
import android.content.Intent.ACTION_PACKAGE_REMOVED
|
||||
import android.content.Intent.ACTION_PACKAGE_REPLACED
|
||||
import android.content.Intent.ACTION_USER_ADDED
|
||||
import android.content.Intent.ACTION_USER_REMOVED
|
||||
import android.content.Intent.EXTRA_CHANGED_PACKAGE_LIST
|
||||
import android.content.Intent.EXTRA_UID
|
||||
import android.content.Intent.EXTRA_USER
|
||||
import android.net.Uri
|
||||
import android.os.Handler
|
||||
import android.os.HandlerThread
|
||||
import android.os.UserHandle
|
||||
import com.android.compatibility.common.util.MoreMatchers.anyOrNull
|
||||
import com.android.server.connectivity.BroadcastReceiveHelper.Delegate
|
||||
import com.android.testutils.DevSdkIgnoreRunner
|
||||
import com.android.testutils.waitForIdle
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.ArgumentCaptor
|
||||
import org.mockito.ArgumentMatchers.argThat
|
||||
import org.mockito.ArgumentMatchers.eq
|
||||
import org.mockito.Mockito.doReturn
|
||||
import org.mockito.Mockito.mock
|
||||
import org.mockito.Mockito.times
|
||||
import org.mockito.Mockito.verify
|
||||
|
||||
private const val TEST_PACKAGE_NAME = "com.example.app"
|
||||
private const val TEST_UID = 1000
|
||||
private const val TIMEOUT_MS = 2000
|
||||
|
||||
private inline fun <reified T> any() = org.mockito.Mockito.any(T::class.java)
|
||||
|
||||
@DevSdkIgnoreRunner.MonitorThreadLeak
|
||||
@RunWith(DevSdkIgnoreRunner::class)
|
||||
class BroadcastReceiveHelperTest {
|
||||
|
||||
private val mockContext = mock(Context::class.java)
|
||||
private val mockDelegate = mock(Delegate::class.java)
|
||||
|
||||
// Create an InOrder object to verify the sequence of delegate calls.
|
||||
private val delegateInOrderVerifier = org.mockito.Mockito.inOrder(mockDelegate)
|
||||
|
||||
// lateinit is used here because thread and handler need to be initialized in the
|
||||
// @Before setUp method.
|
||||
private lateinit var handlerThread: HandlerThread
|
||||
private lateinit var handler: Handler
|
||||
private lateinit var broadcastReceiveHelper: BroadcastReceiveHelper
|
||||
private lateinit var packageReceiver: BroadcastReceiver
|
||||
private lateinit var externalAppReceiver: BroadcastReceiver
|
||||
private lateinit var userReceiver: BroadcastReceiver
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
handlerThread = HandlerThread("TestThread")
|
||||
handlerThread.start()
|
||||
handler = Handler(handlerThread.looper)
|
||||
broadcastReceiveHelper = BroadcastReceiveHelper(mockContext, handler, mockDelegate)
|
||||
|
||||
// Capture intent receivers.
|
||||
doReturn(mockContext).`when`(mockContext).createContextAsUser(UserHandle.ALL, 0)
|
||||
broadcastReceiveHelper.registerReceivers()
|
||||
userReceiver = captureIntentReceiver(ACTION_USER_ADDED)
|
||||
packageReceiver = captureIntentReceiver(ACTION_PACKAGE_ADDED)
|
||||
externalAppReceiver = captureIntentReceiver(ACTION_EXTERNAL_APPLICATIONS_AVAILABLE)
|
||||
}
|
||||
|
||||
private fun captureIntentReceiver(action: String): BroadcastReceiver {
|
||||
val receiverCaptor = ArgumentCaptor.forClass(BroadcastReceiver::class.java)
|
||||
verify(mockContext, times(1)).registerReceiver(
|
||||
receiverCaptor.capture(),
|
||||
argThat { it.hasAction(action) },
|
||||
anyOrNull(String::class.java),
|
||||
eq(handler)
|
||||
)
|
||||
// Return the first match.
|
||||
return receiverCaptor.value
|
||||
}
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
broadcastReceiveHelper.unregisterReceivers()
|
||||
handlerThread.quitSafely()
|
||||
handlerThread.join()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testPackageAdded() {
|
||||
val intent = Intent(ACTION_PACKAGE_ADDED).apply {
|
||||
data = Uri.fromParts("package", TEST_PACKAGE_NAME, null)
|
||||
putExtra(EXTRA_UID, TEST_UID)
|
||||
}
|
||||
processOnHandlerThread { packageReceiver.onReceive(mockContext, intent) }
|
||||
delegateInOrderVerifier.verify(mockDelegate).onPackageAdded(TEST_PACKAGE_NAME, TEST_UID)
|
||||
delegateInOrderVerifier.verifyNoMoreInteractions()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testPackageRemoved() {
|
||||
val intent = Intent(ACTION_PACKAGE_REMOVED).apply {
|
||||
data = Uri.fromParts("package", TEST_PACKAGE_NAME, null)
|
||||
putExtra(EXTRA_UID, TEST_UID)
|
||||
}
|
||||
processOnHandlerThread { packageReceiver.onReceive(mockContext, intent) }
|
||||
delegateInOrderVerifier.verify(mockDelegate).onPackageRemoved(TEST_PACKAGE_NAME, TEST_UID)
|
||||
delegateInOrderVerifier.verifyNoMoreInteractions()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testPackageReplaced() {
|
||||
val intent = Intent(ACTION_PACKAGE_REPLACED).apply {
|
||||
data = Uri.fromParts("package", TEST_PACKAGE_NAME, null)
|
||||
putExtra(EXTRA_UID, TEST_UID)
|
||||
}
|
||||
processOnHandlerThread { packageReceiver.onReceive(mockContext, intent) }
|
||||
delegateInOrderVerifier.verify(mockDelegate).onPackageReplaced(TEST_PACKAGE_NAME, TEST_UID)
|
||||
delegateInOrderVerifier.verifyNoMoreInteractions()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testExternalAppsAvailable() {
|
||||
val packageList = arrayOf("com.example.app1", "com.example.app2")
|
||||
val intent = Intent(ACTION_EXTERNAL_APPLICATIONS_AVAILABLE).apply {
|
||||
putExtra(EXTRA_CHANGED_PACKAGE_LIST, packageList)
|
||||
}
|
||||
processOnHandlerThread { externalAppReceiver.onReceive(mockContext, intent) }
|
||||
delegateInOrderVerifier.verify(mockDelegate).onExternalApplicationsAvailable(packageList)
|
||||
delegateInOrderVerifier.verifyNoMoreInteractions()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testUserAdded() {
|
||||
val userHandle = mock(UserHandle::class.java)
|
||||
val intent = Intent(ACTION_USER_ADDED).apply {
|
||||
putExtra(EXTRA_USER, userHandle)
|
||||
}
|
||||
processOnHandlerThread { userReceiver.onReceive(mockContext, intent) }
|
||||
delegateInOrderVerifier.verify(mockDelegate).onUserAdded(userHandle)
|
||||
delegateInOrderVerifier.verifyNoMoreInteractions()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testUserRemoved() {
|
||||
val userHandle = mock(UserHandle::class.java)
|
||||
val intent = Intent(ACTION_USER_REMOVED).apply {
|
||||
putExtra(EXTRA_USER, userHandle)
|
||||
}
|
||||
processOnHandlerThread { userReceiver.onReceive(mockContext, intent) }
|
||||
delegateInOrderVerifier.verify(mockDelegate).onUserRemoved(userHandle)
|
||||
delegateInOrderVerifier.verifyNoMoreInteractions()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testUnregisterReceivers() {
|
||||
broadcastReceiveHelper.unregisterReceivers()
|
||||
verify(mockContext).unregisterReceiver(userReceiver)
|
||||
verify(mockContext).unregisterReceiver(packageReceiver)
|
||||
verify(mockContext).unregisterReceiver(externalAppReceiver)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testBroadcastOrder() {
|
||||
val numEvents = 50
|
||||
val random = java.util.Random()
|
||||
val eventList = mutableListOf<Intent>()
|
||||
|
||||
// Function to append a test package name extra.
|
||||
fun Intent.withPackageNameForIndex(index: Int): Intent {
|
||||
data = Uri.fromParts("package", "com.example.app$index", null)
|
||||
putExtra(EXTRA_UID, index)
|
||||
return this
|
||||
}
|
||||
|
||||
// Function to append a mock UserHandle extra.
|
||||
fun Intent.withUserHandleForIndex(index: Int): Intent {
|
||||
putExtra(EXTRA_USER, UserHandle.of(index))
|
||||
return this
|
||||
}
|
||||
|
||||
// Generate a list of 50 random actions and their corresponding intents.
|
||||
repeat(numEvents) { index ->
|
||||
val intent = when (random.nextInt(6)) {
|
||||
0 -> Intent(ACTION_PACKAGE_ADDED).withPackageNameForIndex(index)
|
||||
1 -> Intent(ACTION_PACKAGE_REMOVED).withPackageNameForIndex(index)
|
||||
2 -> Intent(ACTION_PACKAGE_REPLACED).withPackageNameForIndex(index)
|
||||
3 -> Intent(ACTION_EXTERNAL_APPLICATIONS_AVAILABLE).apply {
|
||||
val packageList = arrayOf("com.example.app$index")
|
||||
putExtra(EXTRA_CHANGED_PACKAGE_LIST, packageList)
|
||||
}
|
||||
|
||||
4 -> Intent(ACTION_USER_ADDED).withUserHandleForIndex(index)
|
||||
5 -> Intent(ACTION_USER_REMOVED).withUserHandleForIndex(index)
|
||||
|
||||
else -> throw IllegalStateException("Unexpected random number")
|
||||
}
|
||||
eventList.add(intent)
|
||||
}
|
||||
|
||||
// Post all intents to the handler thread at once.
|
||||
eventList.forEach {
|
||||
handler.post {
|
||||
when (it.action) {
|
||||
ACTION_PACKAGE_ADDED, ACTION_PACKAGE_REMOVED, ACTION_PACKAGE_REPLACED ->
|
||||
packageReceiver.onReceive(mockContext, it)
|
||||
|
||||
ACTION_EXTERNAL_APPLICATIONS_AVAILABLE ->
|
||||
externalAppReceiver.onReceive(mockContext, it)
|
||||
|
||||
ACTION_USER_ADDED, ACTION_USER_REMOVED ->
|
||||
userReceiver.onReceive(mockContext, it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Wait for all intents to be processed at once.
|
||||
handler.waitForIdle(TIMEOUT_MS)
|
||||
|
||||
// Verify the order of delegate calls.
|
||||
eventList.forEach {
|
||||
when (it.action) {
|
||||
ACTION_PACKAGE_ADDED -> delegateInOrderVerifier.verify(mockDelegate)
|
||||
.onPackageAdded(
|
||||
it.data?.schemeSpecificPart!!,
|
||||
it.getIntExtra(EXTRA_UID, -1)
|
||||
)
|
||||
|
||||
ACTION_PACKAGE_REMOVED -> delegateInOrderVerifier.verify(mockDelegate)
|
||||
.onPackageRemoved(
|
||||
it.data?.schemeSpecificPart!!,
|
||||
it.getIntExtra(EXTRA_UID, -1)
|
||||
)
|
||||
|
||||
ACTION_PACKAGE_REPLACED -> delegateInOrderVerifier.verify(mockDelegate)
|
||||
.onPackageReplaced(
|
||||
it.data?.schemeSpecificPart!!,
|
||||
it.getIntExtra(EXTRA_UID, -1)
|
||||
)
|
||||
|
||||
ACTION_EXTERNAL_APPLICATIONS_AVAILABLE ->
|
||||
delegateInOrderVerifier.verify(mockDelegate)
|
||||
.onExternalApplicationsAvailable(it.getStringArrayExtra(
|
||||
EXTRA_CHANGED_PACKAGE_LIST
|
||||
)!!)
|
||||
|
||||
ACTION_USER_ADDED -> delegateInOrderVerifier.verify(mockDelegate)
|
||||
.onUserAdded(it.getParcelableExtra(EXTRA_USER)!!)
|
||||
|
||||
ACTION_USER_REMOVED -> delegateInOrderVerifier.verify(mockDelegate)
|
||||
.onUserRemoved(it.getParcelableExtra(EXTRA_USER)!!)
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure no other calls were made to the delegate.
|
||||
delegateInOrderVerifier.verifyNoMoreInteractions()
|
||||
}
|
||||
|
||||
private fun processOnHandlerThread(function: Runnable) {
|
||||
handler.post { function.run() }
|
||||
handler.waitForIdle(HANDLER_TIMEOUT_MS)
|
||||
}
|
||||
}
|
||||
|
|
@ -47,7 +47,6 @@ import static android.permission.PermissionManager.PERMISSION_GRANTED;
|
|||
|
||||
import static com.android.server.connectivity.PermissionMonitor.isHigherNetworkPermission;
|
||||
import static com.android.testutils.TestPermissionUtil.runAsShell;
|
||||
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
|
||||
|
||||
import static junit.framework.Assert.fail;
|
||||
|
||||
|
|
@ -76,9 +75,7 @@ import static org.mockito.Mockito.when;
|
|||
|
||||
import android.compat.testing.PlatformCompatChangeRule;
|
||||
import android.content.AttributionSource;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
|
|
@ -109,6 +106,7 @@ import com.android.networkstack.apishim.ProcessShimImpl;
|
|||
import com.android.networkstack.apishim.common.ProcessShim;
|
||||
import com.android.server.BpfNetMaps;
|
||||
import com.android.testutils.DevSdkIgnoreRule;
|
||||
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
|
||||
import com.android.testutils.DevSdkIgnoreRunner;
|
||||
import com.android.testutils.HandlerUtils;
|
||||
|
||||
|
|
@ -361,6 +359,10 @@ public class PermissionMonitorTest {
|
|||
processOnHandlerThread(() -> mPermissionMonitor.onPackageRemoved(packageName, uid));
|
||||
}
|
||||
|
||||
private void onExternalApplicationsAvailable(String [] pkgList) {
|
||||
processOnHandlerThread(() -> mPermissionMonitor.onExternalApplicationsAvailable(pkgList));
|
||||
}
|
||||
|
||||
private void sendAppIdsTrafficPermission(SparseIntArray netdPermissionsAppIds) {
|
||||
processOnHandlerThread(() ->
|
||||
mPermissionMonitor.sendAppIdsTrafficPermission(netdPermissionsAppIds));
|
||||
|
|
@ -1433,27 +1435,6 @@ public class PermissionMonitorTest {
|
|||
mBpfMapMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_APPID2);
|
||||
}
|
||||
|
||||
private BroadcastReceiver expectBroadcastReceiver(String... actions) {
|
||||
final ArgumentCaptor<BroadcastReceiver> receiverCaptor =
|
||||
ArgumentCaptor.forClass(BroadcastReceiver.class);
|
||||
verify(mContext, times(1)).registerReceiver(receiverCaptor.capture(),
|
||||
argThat(filter -> {
|
||||
for (String action : actions) {
|
||||
if (!filter.hasAction(action)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}), any(), any());
|
||||
final BroadcastReceiver originalReceiver = receiverCaptor.getValue();
|
||||
return new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
processOnHandlerThread(() -> originalReceiver.onReceive(context, intent));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void processOnHandlerThread(Runnable function) {
|
||||
final Handler handler = mHandlerThread.getThreadHandler();
|
||||
handler.post(() -> function.run());
|
||||
|
|
@ -1462,26 +1443,13 @@ public class PermissionMonitorTest {
|
|||
|
||||
@Test
|
||||
@EnableCompatChanges(RESTRICT_LOCAL_NETWORK)
|
||||
public void testIntentReceiver() throws Exception {
|
||||
public void testUidPermissionWhenPackageAddedRemoved() throws Exception {
|
||||
startMonitoring();
|
||||
final BroadcastReceiver receiver = expectBroadcastReceiver(
|
||||
Intent.ACTION_PACKAGE_ADDED, Intent.ACTION_PACKAGE_REMOVED);
|
||||
|
||||
// Verify receiving PACKAGE_ADDED intent.
|
||||
final Intent addedIntent = new Intent(Intent.ACTION_PACKAGE_ADDED,
|
||||
Uri.fromParts("package", MOCK_PACKAGE1, null /* fragment */));
|
||||
addedIntent.putExtra(Intent.EXTRA_UID, MOCK_UID11);
|
||||
buildAndMockPackageInfoWithPermissions(MOCK_PACKAGE1, MOCK_UID11, INTERNET,
|
||||
UPDATE_DEVICE_STATS);
|
||||
receiver.onReceive(mContext, addedIntent);
|
||||
// Add/Remove package and verify uid permissions.
|
||||
addPackage(MOCK_PACKAGE1, MOCK_UID11, INTERNET, UPDATE_DEVICE_STATS);
|
||||
mBpfMapMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_APPID1);
|
||||
|
||||
// Verify receiving PACKAGE_REMOVED intent.
|
||||
when(mPackageManager.getPackagesForUid(MOCK_UID11)).thenReturn(new String[]{});
|
||||
final Intent removedIntent = new Intent(Intent.ACTION_PACKAGE_REMOVED,
|
||||
Uri.fromParts("package", MOCK_PACKAGE1, null /* fragment */));
|
||||
removedIntent.putExtra(Intent.EXTRA_UID, MOCK_UID11);
|
||||
receiver.onReceive(mContext, removedIntent);
|
||||
removePackage(MOCK_PACKAGE1, MOCK_UID11);
|
||||
mBpfMapMonitor.expectTrafficPerm(PERMISSION_UNINSTALLED, MOCK_APPID1);
|
||||
}
|
||||
|
||||
|
|
@ -1634,17 +1602,12 @@ public class PermissionMonitorTest {
|
|||
mNetdMonitor.expectNoNetworkPerm(new UserHandle[]{MOCK_USER1}, MOCK_APPID1, MOCK_APPID2);
|
||||
mBpfMapMonitor.expectTrafficPerm(PERMISSION_NONE, MOCK_APPID1, MOCK_APPID2);
|
||||
|
||||
final BroadcastReceiver receiver = expectBroadcastReceiver(
|
||||
Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
|
||||
// Verify receiving EXTERNAL_APPLICATIONS_AVAILABLE intent and update permission to netd.
|
||||
final Intent externalIntent = new Intent(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
|
||||
externalIntent.putExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST,
|
||||
new String[] { MOCK_PACKAGE1 , MOCK_PACKAGE2});
|
||||
// Call onExternalApplicationsAvailable and verify update permission to netd.
|
||||
buildAndMockPackageInfoWithPermissions(MOCK_PACKAGE1, MOCK_UID11,
|
||||
CONNECTIVITY_USE_RESTRICTED_NETWORKS, INTERNET);
|
||||
buildAndMockPackageInfoWithPermissions(MOCK_PACKAGE2, MOCK_UID12, CHANGE_NETWORK_STATE,
|
||||
UPDATE_DEVICE_STATS);
|
||||
receiver.onReceive(mContext, externalIntent);
|
||||
onExternalApplicationsAvailable(new String[] { MOCK_PACKAGE1 , MOCK_PACKAGE2});
|
||||
mNetdMonitor.expectNetworkPerm(PERMISSION_SYSTEM, new UserHandle[]{MOCK_USER1},
|
||||
MOCK_APPID1);
|
||||
mNetdMonitor.expectNetworkPerm(PERMISSION_NETWORK, new UserHandle[]{MOCK_USER1},
|
||||
|
|
@ -1658,8 +1621,6 @@ public class PermissionMonitorTest {
|
|||
public void testOnExternalApplicationsAvailable_AppsNotRegisteredOnStartMonitoring()
|
||||
throws Exception {
|
||||
startMonitoring();
|
||||
final BroadcastReceiver receiver = expectBroadcastReceiver(
|
||||
Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
|
||||
|
||||
// Initial the permission state. MOCK_PACKAGE1 and MOCK_PACKAGE2 are installed on external
|
||||
// and have different uids. There has no permission for both uids.
|
||||
|
|
@ -1668,11 +1629,8 @@ public class PermissionMonitorTest {
|
|||
buildAndMockPackageInfoWithPermissions(MOCK_PACKAGE2, MOCK_UID12, CHANGE_NETWORK_STATE,
|
||||
UPDATE_DEVICE_STATS);
|
||||
|
||||
// Verify receiving EXTERNAL_APPLICATIONS_AVAILABLE intent and update permission to netd.
|
||||
final Intent externalIntent = new Intent(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
|
||||
externalIntent.putExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST,
|
||||
new String[] { MOCK_PACKAGE1 , MOCK_PACKAGE2});
|
||||
receiver.onReceive(mContext, externalIntent);
|
||||
// Call onExternalApplicationsAvailable and verify update permission to netd.
|
||||
onExternalApplicationsAvailable(new String[] { MOCK_PACKAGE1 , MOCK_PACKAGE2});
|
||||
mNetdMonitor.expectNetworkPerm(PERMISSION_SYSTEM, new UserHandle[]{MOCK_USER1},
|
||||
MOCK_APPID1);
|
||||
mNetdMonitor.expectNetworkPerm(PERMISSION_NETWORK, new UserHandle[]{MOCK_USER1},
|
||||
|
|
@ -1695,14 +1653,10 @@ public class PermissionMonitorTest {
|
|||
mNetdMonitor.expectNoNetworkPerm(new UserHandle[]{MOCK_USER1}, MOCK_APPID1);
|
||||
mBpfMapMonitor.expectTrafficPerm(PERMISSION_NONE, MOCK_APPID1);
|
||||
|
||||
final BroadcastReceiver receiver = expectBroadcastReceiver(
|
||||
Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
|
||||
// Verify receiving EXTERNAL_APPLICATIONS_AVAILABLE intent and update permission to netd.
|
||||
final Intent externalIntent = new Intent(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
|
||||
externalIntent.putExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST, new String[] {MOCK_PACKAGE1});
|
||||
// Call onExternalApplicationsAvailable and verify update permission to netd.
|
||||
buildAndMockPackageInfoWithPermissions(MOCK_PACKAGE1, MOCK_UID11, CHANGE_NETWORK_STATE);
|
||||
buildAndMockPackageInfoWithPermissions(MOCK_PACKAGE2, MOCK_UID11, UPDATE_DEVICE_STATS);
|
||||
receiver.onReceive(mContext, externalIntent);
|
||||
onExternalApplicationsAvailable(new String[] {MOCK_PACKAGE1});
|
||||
mNetdMonitor.expectNetworkPerm(PERMISSION_NETWORK, new UserHandle[]{MOCK_USER1},
|
||||
MOCK_APPID1);
|
||||
mBpfMapMonitor.expectTrafficPerm(PERMISSION_UPDATE_DEVICE_STATS, MOCK_APPID1);
|
||||
|
|
@ -1724,16 +1678,12 @@ public class PermissionMonitorTest {
|
|||
MOCK_APPID1);
|
||||
mBpfMapMonitor.expectTrafficPerm(PERMISSION_INTERNET, MOCK_APPID1);
|
||||
|
||||
final BroadcastReceiver receiver = expectBroadcastReceiver(
|
||||
Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
|
||||
// Verify receiving EXTERNAL_APPLICATIONS_AVAILABLE intent and update permission to netd.
|
||||
final Intent externalIntent = new Intent(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
|
||||
externalIntent.putExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST, new String[] {MOCK_PACKAGE1});
|
||||
// Call onExternalApplicationsAvailable and verify update permission to netd.
|
||||
buildAndMockPackageInfoWithPermissions(MOCK_PACKAGE1, MOCK_UID11,
|
||||
CONNECTIVITY_USE_RESTRICTED_NETWORKS, UPDATE_DEVICE_STATS);
|
||||
buildAndMockPackageInfoWithPermissions(MOCK_PACKAGE2, MOCK_UID11, CHANGE_NETWORK_STATE,
|
||||
INTERNET);
|
||||
receiver.onReceive(mContext, externalIntent);
|
||||
onExternalApplicationsAvailable(new String[] {MOCK_PACKAGE1});
|
||||
mNetdMonitor.expectNetworkPerm(PERMISSION_SYSTEM, new UserHandle[]{MOCK_USER1},
|
||||
MOCK_APPID1);
|
||||
mBpfMapMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_APPID1);
|
||||
|
|
|
|||
Loading…
Reference in a new issue