Set the tether Entitlement app as active when enabling tethering. am: b04fae204e
am: 95fb3f6d3c
Change-Id: I75d28601b83a9b8edffa1f6741767673aaa7dfc0
This commit is contained in:
@@ -20,6 +20,7 @@ import android.app.Activity;
|
|||||||
import android.app.AlarmManager;
|
import android.app.AlarmManager;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
|
import android.app.usage.UsageStatsManager;
|
||||||
import android.bluetooth.BluetoothAdapter;
|
import android.bluetooth.BluetoothAdapter;
|
||||||
import android.bluetooth.BluetoothPan;
|
import android.bluetooth.BluetoothPan;
|
||||||
import android.bluetooth.BluetoothProfile;
|
import android.bluetooth.BluetoothProfile;
|
||||||
@@ -29,6 +30,8 @@ import android.content.Context;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.content.pm.ResolveInfo;
|
||||||
import android.net.ConnectivityManager;
|
import android.net.ConnectivityManager;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.ResultReceiver;
|
import android.os.ResultReceiver;
|
||||||
@@ -63,6 +66,7 @@ public class TetherService extends Service {
|
|||||||
|
|
||||||
private int mCurrentTypeIndex;
|
private int mCurrentTypeIndex;
|
||||||
private boolean mInProvisionCheck;
|
private boolean mInProvisionCheck;
|
||||||
|
private UsageStatsManagerWrapper mUsageManagerWrapper;
|
||||||
private ArrayList<Integer> mCurrentTethers;
|
private ArrayList<Integer> mCurrentTethers;
|
||||||
private ArrayMap<Integer, List<ResultReceiver>> mPendingCallbacks;
|
private ArrayMap<Integer, List<ResultReceiver>> mPendingCallbacks;
|
||||||
|
|
||||||
@@ -87,6 +91,9 @@ public class TetherService extends Service {
|
|||||||
mPendingCallbacks.put(ConnectivityManager.TETHERING_USB, new ArrayList<ResultReceiver>());
|
mPendingCallbacks.put(ConnectivityManager.TETHERING_USB, new ArrayList<ResultReceiver>());
|
||||||
mPendingCallbacks.put(
|
mPendingCallbacks.put(
|
||||||
ConnectivityManager.TETHERING_BLUETOOTH, new ArrayList<ResultReceiver>());
|
ConnectivityManager.TETHERING_BLUETOOTH, new ArrayList<ResultReceiver>());
|
||||||
|
if (mUsageManagerWrapper == null) {
|
||||||
|
mUsageManagerWrapper = new UsageStatsManagerWrapper(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -228,17 +235,43 @@ public class TetherService extends Service {
|
|||||||
|
|
||||||
private void startProvisioning(int index) {
|
private void startProvisioning(int index) {
|
||||||
if (index < mCurrentTethers.size()) {
|
if (index < mCurrentTethers.size()) {
|
||||||
|
Intent intent = getProvisionBroadcastIntent(index);
|
||||||
|
setEntitlementAppActive(index);
|
||||||
|
|
||||||
|
if (DEBUG) Log.d(TAG, "Sending provisioning broadcast: " + intent.getAction()
|
||||||
|
+ " type: " + mCurrentTethers.get(index));
|
||||||
|
|
||||||
|
sendBroadcast(intent);
|
||||||
|
mInProvisionCheck = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Intent getProvisionBroadcastIntent(int index) {
|
||||||
String provisionAction = getResources().getString(
|
String provisionAction = getResources().getString(
|
||||||
com.android.internal.R.string.config_mobile_hotspot_provision_app_no_ui);
|
com.android.internal.R.string.config_mobile_hotspot_provision_app_no_ui);
|
||||||
if (DEBUG) Log.d(TAG, "Sending provisioning broadcast: " + provisionAction + " type: "
|
|
||||||
+ mCurrentTethers.get(index));
|
|
||||||
Intent intent = new Intent(provisionAction);
|
Intent intent = new Intent(provisionAction);
|
||||||
int type = mCurrentTethers.get(index);
|
int type = mCurrentTethers.get(index);
|
||||||
intent.putExtra(TETHER_CHOICE, type);
|
intent.putExtra(TETHER_CHOICE, type);
|
||||||
intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
|
intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
|
||||||
|
|
||||||
sendBroadcast(intent);
|
return intent;
|
||||||
mInProvisionCheck = true;
|
}
|
||||||
|
|
||||||
|
private void setEntitlementAppActive(int index) {
|
||||||
|
final PackageManager packageManager = getPackageManager();
|
||||||
|
Intent intent = getProvisionBroadcastIntent(index);
|
||||||
|
List<ResolveInfo> resolvers =
|
||||||
|
packageManager.queryBroadcastReceivers(intent, PackageManager.MATCH_ALL);
|
||||||
|
if (resolvers.isEmpty()) {
|
||||||
|
Log.e(TAG, "No found BroadcastReceivers for provision intent.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ResolveInfo resolver : resolvers) {
|
||||||
|
if (resolver.activityInfo.applicationInfo.isSystemApp()) {
|
||||||
|
String packageName = resolver.activityInfo.packageName;
|
||||||
|
mUsageManagerWrapper.setAppInactive(packageName, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -335,4 +368,26 @@ public class TetherService extends Service {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
void setUsageStatsManagerWrapper(UsageStatsManagerWrapper wrapper) {
|
||||||
|
mUsageManagerWrapper = wrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A static helper class used for tests. UsageStatsManager cannot be mocked out becasue
|
||||||
|
* it's marked final. This class can be mocked out instead.
|
||||||
|
*/
|
||||||
|
@VisibleForTesting
|
||||||
|
public static class UsageStatsManagerWrapper {
|
||||||
|
private final UsageStatsManager mUsageStatsManager;
|
||||||
|
|
||||||
|
UsageStatsManagerWrapper(Context context) {
|
||||||
|
mUsageStatsManager = (UsageStatsManager)
|
||||||
|
context.getSystemService(Context.USAGE_STATS_SERVICE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setAppInactive(String packageName, boolean isInactive) {
|
||||||
|
mUsageStatsManager.setAppInactive(packageName, isInactive);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -35,11 +35,16 @@ import static android.net.ConnectivityManager.TETHER_ERROR_PROVISION_FAILED;
|
|||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.AlarmManager;
|
import android.app.AlarmManager;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
|
import android.app.usage.UsageStatsManager;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.ContextWrapper;
|
import android.content.ContextWrapper;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
|
import android.content.pm.ActivityInfo;
|
||||||
|
import android.content.pm.ApplicationInfo;
|
||||||
|
import android.content.pm.ResolveInfo;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.content.SharedPreferences.Editor;
|
import android.content.SharedPreferences.Editor;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
@@ -61,10 +66,16 @@ import org.mockito.Mock;
|
|||||||
import org.mockito.MockitoAnnotations;
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public class TetherServiceTest extends ServiceTestCase<TetherService> {
|
public class TetherServiceTest extends ServiceTestCase<TetherService> {
|
||||||
|
|
||||||
private static final String TAG = "TetherServiceTest";
|
private static final String TAG = "TetherServiceTest";
|
||||||
|
private static final String FAKE_PACKAGE_NAME = "com.some.package.name";
|
||||||
|
private static final String ENTITLEMENT_PACKAGE_NAME = "com.some.entitlement.name";
|
||||||
private static final String TEST_RESPONSE_ACTION = "testProvisioningResponseAction";
|
private static final String TEST_RESPONSE_ACTION = "testProvisioningResponseAction";
|
||||||
private static final String TEST_NO_UI_ACTION = "testNoUiProvisioningRequestAction";
|
private static final String TEST_NO_UI_ACTION = "testNoUiProvisioningRequestAction";
|
||||||
private static final int BOGUS_RECEIVER_RESULT = -5;
|
private static final int BOGUS_RECEIVER_RESULT = -5;
|
||||||
@@ -75,6 +86,7 @@ public class TetherServiceTest extends ServiceTestCase<TetherService> {
|
|||||||
|
|
||||||
private TetherService mService;
|
private TetherService mService;
|
||||||
private MockResources mResources;
|
private MockResources mResources;
|
||||||
|
private FakeUsageStatsManagerWrapper mUsageStatsManagerWrapper;
|
||||||
int mLastReceiverResultCode = BOGUS_RECEIVER_RESULT;
|
int mLastReceiverResultCode = BOGUS_RECEIVER_RESULT;
|
||||||
private int mLastTetherRequestType = TETHERING_INVALID;
|
private int mLastTetherRequestType = TETHERING_INVALID;
|
||||||
private int mProvisionResponse = BOGUS_RECEIVER_RESULT;
|
private int mProvisionResponse = BOGUS_RECEIVER_RESULT;
|
||||||
@@ -83,6 +95,7 @@ public class TetherServiceTest extends ServiceTestCase<TetherService> {
|
|||||||
|
|
||||||
@Mock private AlarmManager mAlarmManager;
|
@Mock private AlarmManager mAlarmManager;
|
||||||
@Mock private ConnectivityManager mConnectivityManager;
|
@Mock private ConnectivityManager mConnectivityManager;
|
||||||
|
@Mock private PackageManager mPackageManager;
|
||||||
@Mock private WifiManager mWifiManager;
|
@Mock private WifiManager mWifiManager;
|
||||||
@Mock private SharedPreferences mPrefs;
|
@Mock private SharedPreferences mPrefs;
|
||||||
@Mock private Editor mPrefEditor;
|
@Mock private Editor mPrefEditor;
|
||||||
@@ -115,6 +128,27 @@ public class TetherServiceTest extends ServiceTestCase<TetherService> {
|
|||||||
when(mPrefs.edit()).thenReturn(mPrefEditor);
|
when(mPrefs.edit()).thenReturn(mPrefEditor);
|
||||||
when(mPrefEditor.putString(eq(CURRENT_TYPES), mStoredTypes.capture())).thenReturn(
|
when(mPrefEditor.putString(eq(CURRENT_TYPES), mStoredTypes.capture())).thenReturn(
|
||||||
mPrefEditor);
|
mPrefEditor);
|
||||||
|
mUsageStatsManagerWrapper = new FakeUsageStatsManagerWrapper(mContext);
|
||||||
|
|
||||||
|
ResolveInfo systemAppResolveInfo = new ResolveInfo();
|
||||||
|
ActivityInfo systemActivityInfo = new ActivityInfo();
|
||||||
|
systemActivityInfo.packageName = ENTITLEMENT_PACKAGE_NAME;
|
||||||
|
ApplicationInfo systemAppInfo = new ApplicationInfo();
|
||||||
|
systemAppInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
|
||||||
|
systemActivityInfo.applicationInfo = systemAppInfo;
|
||||||
|
systemAppResolveInfo.activityInfo = systemActivityInfo;
|
||||||
|
|
||||||
|
ResolveInfo nonSystemResolveInfo = new ResolveInfo();
|
||||||
|
ActivityInfo nonSystemActivityInfo = new ActivityInfo();
|
||||||
|
nonSystemActivityInfo.packageName = FAKE_PACKAGE_NAME;
|
||||||
|
nonSystemActivityInfo.applicationInfo = new ApplicationInfo();
|
||||||
|
nonSystemResolveInfo.activityInfo = nonSystemActivityInfo;
|
||||||
|
|
||||||
|
List<ResolveInfo> resolvers = new ArrayList();
|
||||||
|
resolvers.add(nonSystemResolveInfo);
|
||||||
|
resolvers.add(systemAppResolveInfo);
|
||||||
|
when(mPackageManager.queryBroadcastReceivers(
|
||||||
|
any(Intent.class), eq(PackageManager.MATCH_ALL))).thenReturn(resolvers);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -139,6 +173,19 @@ public class TetherServiceTest extends ServiceTestCase<TetherService> {
|
|||||||
assertTrue(waitForProvisionResponse(TETHER_ERROR_NO_ERROR));
|
assertTrue(waitForProvisionResponse(TETHER_ERROR_NO_ERROR));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testStartKeepsProvisionAppActive() {
|
||||||
|
setupService();
|
||||||
|
getService().setUsageStatsManagerWrapper(mUsageStatsManagerWrapper);
|
||||||
|
|
||||||
|
runProvisioningForType(TETHERING_WIFI);
|
||||||
|
|
||||||
|
assertTrue(waitForProvisionRequest(TETHERING_WIFI));
|
||||||
|
assertTrue(waitForProvisionResponse(TETHER_ERROR_NO_ERROR));
|
||||||
|
assertFalse(mUsageStatsManagerWrapper.isAppInactive(ENTITLEMENT_PACKAGE_NAME));
|
||||||
|
// Non-system handler of the intent action should stay idle.
|
||||||
|
assertTrue(mUsageStatsManagerWrapper.isAppInactive(FAKE_PACKAGE_NAME));
|
||||||
|
}
|
||||||
|
|
||||||
public void testScheduleRechecks() {
|
public void testScheduleRechecks() {
|
||||||
Intent intent = new Intent();
|
Intent intent = new Intent();
|
||||||
intent.putExtra(EXTRA_ADD_TETHER_TYPE, TETHERING_WIFI);
|
intent.putExtra(EXTRA_ADD_TETHER_TYPE, TETHERING_WIFI);
|
||||||
@@ -229,6 +276,19 @@ public class TetherServiceTest extends ServiceTestCase<TetherService> {
|
|||||||
startService(intent);
|
startService(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean waitForAppInactive(UsageStatsManager usageStatsManager, String packageName) {
|
||||||
|
long startTime = SystemClock.uptimeMillis();
|
||||||
|
while (true) {
|
||||||
|
if (usageStatsManager.isAppInactive(packageName)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ((SystemClock.uptimeMillis() - startTime) > PROVISION_TIMEOUT) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
SystemClock.sleep(SHORT_TIMEOUT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private boolean waitForProvisionRequest(int expectedType) {
|
private boolean waitForProvisionRequest(int expectedType) {
|
||||||
long startTime = SystemClock.uptimeMillis();
|
long startTime = SystemClock.uptimeMillis();
|
||||||
while (true) {
|
while (true) {
|
||||||
@@ -307,6 +367,11 @@ public class TetherServiceTest extends ServiceTestCase<TetherService> {
|
|||||||
return super.getSharedPreferences(name, mode);
|
return super.getSharedPreferences(name, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PackageManager getPackageManager() {
|
||||||
|
return mPackageManager;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getSystemService(String name) {
|
public Object getSystemService(String name) {
|
||||||
if (ALARM_SERVICE.equals(name)) {
|
if (ALARM_SERVICE.equals(name)) {
|
||||||
@@ -355,4 +420,27 @@ public class TetherServiceTest extends ServiceTestCase<TetherService> {
|
|||||||
responseIntent, android.Manifest.permission.CONNECTIVITY_INTERNAL);
|
responseIntent, android.Manifest.permission.CONNECTIVITY_INTERNAL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class FakeUsageStatsManagerWrapper
|
||||||
|
extends TetherService.UsageStatsManagerWrapper {
|
||||||
|
private final Set<String> mActivePackages;
|
||||||
|
|
||||||
|
FakeUsageStatsManagerWrapper(Context context) {
|
||||||
|
super(context);
|
||||||
|
mActivePackages = new HashSet<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void setAppInactive(String packageName, boolean isInactive) {
|
||||||
|
if (!isInactive) {
|
||||||
|
mActivePackages.add(packageName);
|
||||||
|
} else {
|
||||||
|
mActivePackages.remove(packageName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isAppInactive(String packageName) {
|
||||||
|
return !mActivePackages.contains(packageName);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user