Merge "Support entitlement check in DSDS"
This commit is contained in:
@@ -443,7 +443,7 @@
|
|||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:permission="android.permission.TETHER_PRIVILEGED" />
|
android:permission="android.permission.TETHER_PRIVILEGED" />
|
||||||
|
|
||||||
<activity android:name="TetherProvisioningActivity"
|
<activity android:name="network.TetherProvisioningActivity"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:permission="android.permission.TETHER_PRIVILEGED"
|
android:permission="android.permission.TETHER_PRIVILEGED"
|
||||||
android:excludeFromRecents="true"
|
android:excludeFromRecents="true"
|
||||||
|
@@ -71,6 +71,7 @@ import android.provider.ContactsContract.Data;
|
|||||||
import android.provider.ContactsContract.Profile;
|
import android.provider.ContactsContract.Profile;
|
||||||
import android.provider.ContactsContract.RawContacts;
|
import android.provider.ContactsContract.RawContacts;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
|
import android.telephony.SubscriptionManager;
|
||||||
import android.telephony.TelephonyManager;
|
import android.telephony.TelephonyManager;
|
||||||
import android.text.Spannable;
|
import android.text.Spannable;
|
||||||
import android.text.SpannableString;
|
import android.text.SpannableString;
|
||||||
@@ -980,4 +981,13 @@ public final class Utils extends com.android.settingslib.Utils {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Get {@link Resources} by subscription id if subscription id is valid. */
|
||||||
|
public static Resources getResourcesForSubId(Context context, int subId) {
|
||||||
|
if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
|
||||||
|
return SubscriptionManager.getResourcesForSubId(context, subId);
|
||||||
|
} else {
|
||||||
|
return context.getResources();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -14,17 +14,21 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.android.settings;
|
package com.android.settings.network;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
|
import android.content.res.Resources;
|
||||||
import android.net.ConnectivityManager;
|
import android.net.ConnectivityManager;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.ResultReceiver;
|
import android.os.ResultReceiver;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
|
import android.telephony.SubscriptionManager;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.android.settings.Utils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Activity which acts as a proxy to the tether provisioning app for sanity checks and permission
|
* Activity which acts as a proxy to the tether provisioning app for sanity checks and permission
|
||||||
* restrictions. Specifically, the provisioning apps require
|
* restrictions. Specifically, the provisioning apps require
|
||||||
@@ -47,7 +51,9 @@ public class TetherProvisioningActivity extends Activity {
|
|||||||
|
|
||||||
int tetherType = getIntent().getIntExtra(ConnectivityManager.EXTRA_ADD_TETHER_TYPE,
|
int tetherType = getIntent().getIntExtra(ConnectivityManager.EXTRA_ADD_TETHER_TYPE,
|
||||||
ConnectivityManager.TETHERING_INVALID);
|
ConnectivityManager.TETHERING_INVALID);
|
||||||
String[] provisionApp = getResources().getStringArray(
|
final int subId = SubscriptionManager.getDefaultDataSubscriptionId();
|
||||||
|
final Resources res = Utils.getResourcesForSubId(this, subId);
|
||||||
|
final String[] provisionApp = res.getStringArray(
|
||||||
com.android.internal.R.array.config_mobile_hotspot_provision_app);
|
com.android.internal.R.array.config_mobile_hotspot_provision_app);
|
||||||
|
|
||||||
Intent intent = new Intent(Intent.ACTION_MAIN);
|
Intent intent = new Intent(Intent.ACTION_MAIN);
|
@@ -32,16 +32,20 @@ import android.content.IntentFilter;
|
|||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.pm.ResolveInfo;
|
import android.content.pm.ResolveInfo;
|
||||||
|
import android.content.res.Resources;
|
||||||
import android.net.ConnectivityManager;
|
import android.net.ConnectivityManager;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.ResultReceiver;
|
import android.os.ResultReceiver;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
|
import android.telephony.SubscriptionManager;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.ArrayMap;
|
import android.util.ArrayMap;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import androidx.annotation.VisibleForTesting;
|
import androidx.annotation.VisibleForTesting;
|
||||||
|
|
||||||
|
import com.android.settings.Utils;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -65,7 +69,7 @@ public class TetherService extends Service {
|
|||||||
|
|
||||||
private int mCurrentTypeIndex;
|
private int mCurrentTypeIndex;
|
||||||
private boolean mInProvisionCheck;
|
private boolean mInProvisionCheck;
|
||||||
private UsageStatsManagerWrapper mUsageManagerWrapper;
|
private TetherServiceWrapper mWrapper;
|
||||||
private ArrayList<Integer> mCurrentTethers;
|
private ArrayList<Integer> mCurrentTethers;
|
||||||
private ArrayMap<Integer, List<ResultReceiver>> mPendingCallbacks;
|
private ArrayMap<Integer, List<ResultReceiver>> mPendingCallbacks;
|
||||||
private HotspotOffReceiver mHotspotReceiver;
|
private HotspotOffReceiver mHotspotReceiver;
|
||||||
@@ -79,7 +83,7 @@ public class TetherService extends Service {
|
|||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
if (DEBUG) Log.d(TAG, "Creating TetherService");
|
if (DEBUG) Log.d(TAG, "Creating TetherService");
|
||||||
String provisionResponse = getResources().getString(
|
String provisionResponse = getResourceForDefaultDataSubId().getString(
|
||||||
com.android.internal.R.string.config_mobile_hotspot_provision_response);
|
com.android.internal.R.string.config_mobile_hotspot_provision_response);
|
||||||
registerReceiver(mReceiver, new IntentFilter(provisionResponse),
|
registerReceiver(mReceiver, new IntentFilter(provisionResponse),
|
||||||
android.Manifest.permission.CONNECTIVITY_INTERNAL, null);
|
android.Manifest.permission.CONNECTIVITY_INTERNAL, null);
|
||||||
@@ -91,9 +95,6 @@ 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);
|
|
||||||
}
|
|
||||||
mHotspotReceiver = new HotspotOffReceiver(this);
|
mHotspotReceiver = new HotspotOffReceiver(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -258,7 +259,7 @@ public class TetherService extends Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Intent getProvisionBroadcastIntent(int index) {
|
private Intent getProvisionBroadcastIntent(int index) {
|
||||||
String provisionAction = getResources().getString(
|
String provisionAction = getResourceForDefaultDataSubId().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);
|
||||||
Intent intent = new Intent(provisionAction);
|
Intent intent = new Intent(provisionAction);
|
||||||
int type = mCurrentTethers.get(index);
|
int type = mCurrentTethers.get(index);
|
||||||
@@ -282,7 +283,7 @@ public class TetherService extends Service {
|
|||||||
for (ResolveInfo resolver : resolvers) {
|
for (ResolveInfo resolver : resolvers) {
|
||||||
if (resolver.activityInfo.applicationInfo.isSystemApp()) {
|
if (resolver.activityInfo.applicationInfo.isSystemApp()) {
|
||||||
String packageName = resolver.activityInfo.packageName;
|
String packageName = resolver.activityInfo.packageName;
|
||||||
mUsageManagerWrapper.setAppInactive(packageName, false);
|
getTetherServiceWrapper().setAppInactive(packageName, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -294,7 +295,7 @@ public class TetherService extends Service {
|
|||||||
|
|
||||||
PendingIntent pendingIntent = PendingIntent.getService(this, 0, intent, 0);
|
PendingIntent pendingIntent = PendingIntent.getService(this, 0, intent, 0);
|
||||||
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
|
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
|
||||||
int period = getResources().getInteger(
|
int period = getResourceForDefaultDataSubId().getInteger(
|
||||||
com.android.internal.R.integer.config_mobile_hotspot_provision_check_period);
|
com.android.internal.R.integer.config_mobile_hotspot_provision_check_period);
|
||||||
long periodMs = period * MS_PER_HOUR;
|
long periodMs = period * MS_PER_HOUR;
|
||||||
long firstTime = SystemClock.elapsedRealtime() + periodMs;
|
long firstTime = SystemClock.elapsedRealtime() + periodMs;
|
||||||
@@ -347,7 +348,7 @@ public class TetherService extends Service {
|
|||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
if (DEBUG) Log.d(TAG, "Got provision result " + intent);
|
if (DEBUG) Log.d(TAG, "Got provision result " + intent);
|
||||||
String provisionResponse = getResources().getString(
|
String provisionResponse = getResourceForDefaultDataSubId().getString(
|
||||||
com.android.internal.R.string.config_mobile_hotspot_provision_response);
|
com.android.internal.R.string.config_mobile_hotspot_provision_response);
|
||||||
|
|
||||||
if (provisionResponse.equals(intent.getAction())) {
|
if (provisionResponse.equals(intent.getAction())) {
|
||||||
@@ -385,19 +386,27 @@ public class TetherService extends Service {
|
|||||||
};
|
};
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
void setUsageStatsManagerWrapper(UsageStatsManagerWrapper wrapper) {
|
void setTetherServiceWrapper(TetherServiceWrapper wrapper) {
|
||||||
mUsageManagerWrapper = wrapper;
|
mWrapper = wrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
private TetherServiceWrapper getTetherServiceWrapper() {
|
||||||
|
if (mWrapper == null) {
|
||||||
|
mWrapper = new TetherServiceWrapper(this);
|
||||||
|
}
|
||||||
|
return mWrapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A static helper class used for tests. UsageStatsManager cannot be mocked out becasue
|
* A static helper class used for tests. UsageStatsManager cannot be mocked out because
|
||||||
* it's marked final. This class can be mocked out instead.
|
* it's marked final. Static method SubscriptionManager#getResourcesForSubId also cannot
|
||||||
|
* be mocked. This class can be mocked out instead.
|
||||||
*/
|
*/
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public static class UsageStatsManagerWrapper {
|
public static class TetherServiceWrapper {
|
||||||
private final UsageStatsManager mUsageStatsManager;
|
private final UsageStatsManager mUsageStatsManager;
|
||||||
|
|
||||||
UsageStatsManagerWrapper(Context context) {
|
TetherServiceWrapper(Context context) {
|
||||||
mUsageStatsManager = (UsageStatsManager)
|
mUsageStatsManager = (UsageStatsManager)
|
||||||
context.getSystemService(Context.USAGE_STATS_SERVICE);
|
context.getSystemService(Context.USAGE_STATS_SERVICE);
|
||||||
}
|
}
|
||||||
@@ -405,5 +414,15 @@ public class TetherService extends Service {
|
|||||||
void setAppInactive(String packageName, boolean isInactive) {
|
void setAppInactive(String packageName, boolean isInactive) {
|
||||||
mUsageStatsManager.setAppInactive(packageName, isInactive);
|
mUsageStatsManager.setAppInactive(packageName, isInactive);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int getDefaultDataSubscriptionId() {
|
||||||
|
return SubscriptionManager.getDefaultDataSubscriptionId();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
Resources getResourceForDefaultDataSubId() {
|
||||||
|
final int subId = getTetherServiceWrapper().getDefaultDataSubscriptionId();
|
||||||
|
return Utils.getResourcesForSubId(this, subId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -27,6 +27,8 @@ import static android.net.ConnectivityManager.TETHERING_USB;
|
|||||||
import static android.net.ConnectivityManager.TETHERING_WIFI;
|
import static android.net.ConnectivityManager.TETHERING_WIFI;
|
||||||
import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR;
|
import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR;
|
||||||
import static android.net.ConnectivityManager.TETHER_ERROR_PROVISION_FAILED;
|
import static android.net.ConnectivityManager.TETHER_ERROR_PROVISION_FAILED;
|
||||||
|
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
|
||||||
|
|
||||||
import static org.mockito.Matchers.any;
|
import static org.mockito.Matchers.any;
|
||||||
import static org.mockito.Matchers.anyLong;
|
import static org.mockito.Matchers.anyLong;
|
||||||
import static org.mockito.Matchers.eq;
|
import static org.mockito.Matchers.eq;
|
||||||
@@ -83,7 +85,7 @@ public class TetherServiceTest extends ServiceTestCase<TetherService> {
|
|||||||
|
|
||||||
private TetherService mService;
|
private TetherService mService;
|
||||||
private MockResources mResources;
|
private MockResources mResources;
|
||||||
private FakeUsageStatsManagerWrapper mUsageStatsManagerWrapper;
|
private MockTetherServiceWrapper mWrapper;
|
||||||
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;
|
||||||
@@ -125,7 +127,7 @@ 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);
|
mWrapper = new MockTetherServiceWrapper(mContext);
|
||||||
|
|
||||||
ResolveInfo systemAppResolveInfo = new ResolveInfo();
|
ResolveInfo systemAppResolveInfo = new ResolveInfo();
|
||||||
ActivityInfo systemActivityInfo = new ActivityInfo();
|
ActivityInfo systemActivityInfo = new ActivityInfo();
|
||||||
@@ -146,6 +148,8 @@ public class TetherServiceTest extends ServiceTestCase<TetherService> {
|
|||||||
resolvers.add(systemAppResolveInfo);
|
resolvers.add(systemAppResolveInfo);
|
||||||
when(mPackageManager.queryBroadcastReceivers(
|
when(mPackageManager.queryBroadcastReceivers(
|
||||||
any(Intent.class), eq(PackageManager.MATCH_ALL))).thenReturn(resolvers);
|
any(Intent.class), eq(PackageManager.MATCH_ALL))).thenReturn(resolvers);
|
||||||
|
setupService();
|
||||||
|
getService().setTetherServiceWrapper(mWrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -171,16 +175,13 @@ public class TetherServiceTest extends ServiceTestCase<TetherService> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testStartKeepsProvisionAppActive() {
|
public void testStartKeepsProvisionAppActive() {
|
||||||
setupService();
|
|
||||||
getService().setUsageStatsManagerWrapper(mUsageStatsManagerWrapper);
|
|
||||||
|
|
||||||
runProvisioningForType(TETHERING_WIFI);
|
runProvisioningForType(TETHERING_WIFI);
|
||||||
|
|
||||||
assertTrue(waitForProvisionRequest(TETHERING_WIFI));
|
assertTrue(waitForProvisionRequest(TETHERING_WIFI));
|
||||||
assertTrue(waitForProvisionResponse(TETHER_ERROR_NO_ERROR));
|
assertTrue(waitForProvisionResponse(TETHER_ERROR_NO_ERROR));
|
||||||
assertFalse(mUsageStatsManagerWrapper.isAppInactive(ENTITLEMENT_PACKAGE_NAME));
|
assertFalse(mWrapper.isAppInactive(ENTITLEMENT_PACKAGE_NAME));
|
||||||
// Non-system handler of the intent action should stay idle.
|
// Non-system handler of the intent action should stay idle.
|
||||||
assertTrue(mUsageStatsManagerWrapper.isAppInactive(FAKE_PACKAGE_NAME));
|
assertTrue(mWrapper.isAppInactive(FAKE_PACKAGE_NAME));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testScheduleRechecks() {
|
public void testScheduleRechecks() {
|
||||||
@@ -419,11 +420,11 @@ public class TetherServiceTest extends ServiceTestCase<TetherService> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class FakeUsageStatsManagerWrapper
|
private static class MockTetherServiceWrapper
|
||||||
extends TetherService.UsageStatsManagerWrapper {
|
extends TetherService.TetherServiceWrapper {
|
||||||
private final Set<String> mActivePackages;
|
private final Set<String> mActivePackages;
|
||||||
|
|
||||||
FakeUsageStatsManagerWrapper(Context context) {
|
MockTetherServiceWrapper(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
mActivePackages = new HashSet<>();
|
mActivePackages = new HashSet<>();
|
||||||
}
|
}
|
||||||
@@ -440,5 +441,10 @@ public class TetherServiceTest extends ServiceTestCase<TetherService> {
|
|||||||
boolean isAppInactive(String packageName) {
|
boolean isAppInactive(String packageName) {
|
||||||
return !mActivePackages.contains(packageName);
|
return !mActivePackages.contains(packageName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
int getDefaultDataSubscriptionId() {
|
||||||
|
return INVALID_SUBSCRIPTION_ID;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user