Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 481816a9 authored by Mark Chien's avatar Mark Chien Committed by Android (Google) Code Review
Browse files

Merge "Get entitlement configuration from intent extra" into rvc-dev

parents 7084631b e22bd7a2
Loading
Loading
Loading
Loading
+11 −11
Original line number Diff line number Diff line
@@ -18,7 +18,6 @@ package com.android.settings.network;

import static android.net.TetheringConstants.EXTRA_ADD_TETHER_TYPE;
import static android.net.TetheringConstants.EXTRA_PROVISION_CALLBACK;
import static android.net.TetheringConstants.EXTRA_RUN_PROVISION;
import static android.net.TetheringManager.TETHERING_INVALID;
import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
import static android.net.TetheringManager.TETHER_ERROR_PROVISIONING_FAILED;
@@ -28,7 +27,6 @@ import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.os.Bundle;
import android.os.ResultReceiver;
import android.os.UserHandle;
@@ -37,8 +35,6 @@ import android.util.Log;

import androidx.annotation.VisibleForTesting;

import com.android.settings.Utils;

/**
 * Activity which acts as a proxy to the tether provisioning app for sanity checks and permission
 * restrictions. Specifically, the provisioning apps require
@@ -53,7 +49,10 @@ public class TetherProvisioningActivity extends Activity {
    @VisibleForTesting
    static final int PROVISION_REQUEST = 0;
    @VisibleForTesting
    static final String EXTRA_SUBID = "subId";
    static final String EXTRA_TETHER_SUBID = "android.net.extra.TETHER_SUBID";
    @VisibleForTesting
    public static final String EXTRA_TETHER_UI_PROVISIONING_APP_NAME =
            "android.net.extra.TETHER_UI_PROVISIONING_APP_NAME";

    @Override
    public void onCreate(Bundle savedInstanceState) {
@@ -62,7 +61,8 @@ public class TetherProvisioningActivity extends Activity {

        final int tetherType = getIntent().getIntExtra(EXTRA_ADD_TETHER_TYPE, TETHERING_INVALID);

        final int tetherSubId = getIntent().getIntExtra(EXTRA_SUBID, INVALID_SUBSCRIPTION_ID);
        final int tetherSubId = getIntent().getIntExtra(
                EXTRA_TETHER_SUBID, INVALID_SUBSCRIPTION_ID);
        final int subId = SubscriptionManager.getActiveDataSubscriptionId();
        if (tetherSubId != subId) {
            Log.e(TAG, "This Provisioning request is outdated, current subId: " + subId);
@@ -70,11 +70,11 @@ public class TetherProvisioningActivity extends Activity {
            finish();
            return;
        }
        String[] provisionApp = getIntent().getStringArrayExtra(EXTRA_RUN_PROVISION);
        if (provisionApp == null || provisionApp.length < 2) {
            final Resources res = Utils.getResourcesForSubId(this, subId);
            provisionApp = res.getStringArray(
                    com.android.internal.R.array.config_mobile_hotspot_provision_app);
        String[] provisionApp = getIntent().getStringArrayExtra(
                EXTRA_TETHER_UI_PROVISIONING_APP_NAME);
        if (provisionApp == null || provisionApp.length != 2) {
            Log.e(TAG, "Unexpected provision app configuration");
            return;
        }
        final Intent intent = new Intent(Intent.ACTION_MAIN);
        intent.setClassName(provisionApp[0], provisionApp[1]);
+91 −55
Original line number Diff line number Diff line
@@ -41,7 +41,6 @@ import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.net.TetheringManager;
import android.os.IBinder;
import android.os.ResultReceiver;
@@ -52,10 +51,9 @@ import android.util.Log;

import androidx.annotation.VisibleForTesting;

import com.android.settings.Utils;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

public class TetherService extends Service {
    private static final String TAG = "TetherService";
@@ -64,7 +62,13 @@ public class TetherService extends Service {
    @VisibleForTesting
    public static final String EXTRA_RESULT = "EntitlementResult";
    @VisibleForTesting
    public static final String EXTRA_SUBID = "subId";
    public static final String EXTRA_TETHER_SUBID = "android.net.extra.TETHER_SUBID";
    @VisibleForTesting
    public static final String EXTRA_TETHER_PROVISIONING_RESPONSE =
            "android.net.extra.TETHER_PROVISIONING_RESPONSE";
    @VisibleForTesting
    public static final String EXTRA_TETHER_SILENT_PROVISIONING_ACTION =
            "android.net.extra.TETHER_SILENT_PROVISIONING_ACTION";

    // Activity results to match the activity provision protocol.
    // Default to something not ok.
@@ -79,6 +83,11 @@ public class TetherService extends Service {

    private int mCurrentTypeIndex;
    private boolean mInProvisionCheck;
    /** Intent action received from the provisioning app when entitlement check completes. */
    private String mExpectedProvisionResponseAction = null;
    /** Intent action sent to the provisioning app to request an entitlement check. */
    private String mProvisionAction;
    private int mSubId = INVALID_SUBSCRIPTION_ID;
    private TetherServiceWrapper mWrapper;
    private ArrayList<Integer> mCurrentTethers;
    private ArrayMap<Integer, List<ResultReceiver>> mPendingCallbacks;
@@ -92,10 +101,6 @@ public class TetherService extends Service {
    public void onCreate() {
        super.onCreate();
        if (DEBUG) Log.d(TAG, "Creating TetherService");
        String provisionResponse = getResourceForActiveDataSubId().getString(
                com.android.internal.R.string.config_mobile_hotspot_provision_response);
        registerReceiver(mReceiver, new IntentFilter(provisionResponse),
                android.Manifest.permission.TETHER_PRIVILEGED, null);
        SharedPreferences prefs = getSharedPreferences(PREFS, MODE_PRIVATE);
        mCurrentTethers = stringToTethers(prefs.getString(KEY_TETHERS, ""));
        mCurrentTypeIndex = 0;
@@ -106,10 +111,28 @@ public class TetherService extends Service {
        mPendingCallbacks.put(TETHERING_ETHERNET, new ArrayList<ResultReceiver>());
    }

    // Registers the broadcast receiver for the specified response action, first unregistering
    // the receiver if it was registered for a different response action.
    private void maybeRegisterReceiver(final String responseAction) {
        if (Objects.equals(responseAction, mExpectedProvisionResponseAction)) return;

        if (mExpectedProvisionResponseAction != null) unregisterReceiver(mReceiver);

        registerReceiver(mReceiver, new IntentFilter(responseAction),
                android.Manifest.permission.TETHER_PRIVILEGED, null /* handler */);
        mExpectedProvisionResponseAction = responseAction;
        if (DEBUG) Log.d(TAG, "registerReceiver " + responseAction);
    }

    private int stopSelfAndStartNotSticky() {
        stopSelf();
        return START_NOT_STICKY;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (intent.hasExtra(EXTRA_SUBID)) {
            final int tetherSubId = intent.getIntExtra(EXTRA_SUBID, INVALID_SUBSCRIPTION_ID);
        if (intent.hasExtra(EXTRA_TETHER_SUBID)) {
            final int tetherSubId = intent.getIntExtra(EXTRA_TETHER_SUBID, INVALID_SUBSCRIPTION_ID);
            final int subId = getTetherServiceWrapper().getActiveDataSubscriptionId();
            if (tetherSubId != subId) {
                Log.e(TAG, "This Provisioning request is outdated, current subId: " + subId);
@@ -118,7 +141,9 @@ public class TetherService extends Service {
                }
                return START_NOT_STICKY;
            }
            mSubId = subId;
        }

        if (intent.hasExtra(EXTRA_ADD_TETHER_TYPE)) {
            int type = intent.getIntExtra(EXTRA_ADD_TETHER_TYPE, TETHERING_INVALID);
            ResultReceiver callback = intent.getParcelableExtra(EXTRA_PROVISION_CALLBACK);
@@ -128,9 +153,9 @@ public class TetherService extends Service {
                    callbacksForType.add(callback);
                } else {
                    // Invalid tether type. Just ignore this request and report failure.
                    Log.e(TAG, "Invalid tethering type " + type + ", stopping");
                    callback.send(TETHER_ERROR_UNKNOWN_IFACE, null);
                    stopSelf();
                    return START_NOT_STICKY;
                    return stopSelfAndStartNotSticky();
                }
            }

@@ -140,6 +165,19 @@ public class TetherService extends Service {
            }
        }

        mProvisionAction = intent.getStringExtra(EXTRA_TETHER_SILENT_PROVISIONING_ACTION);
        if (mProvisionAction == null) {
            Log.e(TAG, "null provisioning action, stop ");
            return stopSelfAndStartNotSticky();
        }

        final String response = intent.getStringExtra(EXTRA_TETHER_PROVISIONING_RESPONSE);
        if (response == null) {
            Log.e(TAG, "null provisioning response, stop ");
            return stopSelfAndStartNotSticky();
        }
        maybeRegisterReceiver(response);

        if (intent.hasExtra(EXTRA_REM_TETHER_TYPE)) {
            if (!mInProvisionCheck) {
                int type = intent.getIntExtra(EXTRA_REM_TETHER_TYPE, TETHERING_INVALID);
@@ -158,8 +196,7 @@ public class TetherService extends Service {
        } else if (!mInProvisionCheck) {
            // If we aren't running any provisioning, no reason to stay alive.
            if (DEBUG) Log.d(TAG, "Stopping self.  startid: " + startId);
            stopSelf();
            return START_NOT_STICKY;
            return stopSelfAndStartNotSticky();
        }
        // We want to be started if we are killed accidently, so that we can be sure we finish
        // the check.
@@ -175,7 +212,10 @@ public class TetherService extends Service {
        SharedPreferences prefs = getSharedPreferences(PREFS, MODE_PRIVATE);
        prefs.edit().putString(KEY_TETHERS, tethersToString(mCurrentTethers)).commit();

        if (mExpectedProvisionResponseAction != null) {
            unregisterReceiver(mReceiver);
            mExpectedProvisionResponseAction = null;
        }
        if (DEBUG) Log.d(TAG, "Destroying TetherService");
        super.onDestroy();
    }
@@ -220,26 +260,26 @@ public class TetherService extends Service {
    }

    private void startProvisioning(int index) {
        if (index < mCurrentTethers.size()) {
        if (index >= mCurrentTethers.size()) return;

        Intent intent = getProvisionBroadcastIntent(index);
        setEntitlementAppActive(index);

            if (DEBUG) Log.d(TAG, "Sending provisioning broadcast: " + intent.getAction()
        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 = getResourceForActiveDataSubId().getString(
                com.android.internal.R.string.config_mobile_hotspot_provision_app_no_ui);
        final int subId = getTetherServiceWrapper().getActiveDataSubscriptionId();
        Intent intent = new Intent(provisionAction);
        if (mProvisionAction == null) Log.wtf(TAG, "null provisioning action");
        Intent intent = new Intent(mProvisionAction);
        int type = mCurrentTethers.get(index);
        intent.putExtra(TETHER_CHOICE, type);
        intent.putExtra(EXTRA_SUBSCRIPTION_INDEX, subId);
        intent.putExtra(EXTRA_SUBSCRIPTION_INDEX, mSubId);
        intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND
                | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);

@@ -282,12 +322,16 @@ public class TetherService extends Service {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (DEBUG) Log.d(TAG, "Got provision result " + intent);
            String provisionResponse = getResourceForActiveDataSubId().getString(
                    com.android.internal.R.string.config_mobile_hotspot_provision_response);

            if (provisionResponse.equals(intent.getAction())) {
            if (!intent.getAction().equals(mExpectedProvisionResponseAction)) {
                Log.e(TAG, "Received provisioning response for unexpected action="
                        + intent.getAction() + ", expected=" + mExpectedProvisionResponseAction);
                return;
            }

            if (!mInProvisionCheck) {
                    Log.e(TAG, "Unexpected provision response " + intent);
                Log.e(TAG, "Unexpected provisioning response when not in provisioning check"
                        + intent);
                return;
            }
            int checkType = mCurrentTethers.get(mCurrentTypeIndex);
@@ -304,7 +348,6 @@ public class TetherService extends Service {
                startProvisioning(mCurrentTypeIndex);
            }
        }
        }
    };

    @VisibleForTesting
@@ -321,8 +364,7 @@ public class TetherService extends Service {

    /**
     * A static helper class used for tests. UsageStatsManager cannot be mocked out because
     * it's marked final. Static method SubscriptionManager#getResourcesForSubId also cannot
     * be mocked. This class can be mocked out instead.
     * it's marked final. This class can be mocked out instead.
     */
    @VisibleForTesting
    public static class TetherServiceWrapper {
@@ -341,10 +383,4 @@ public class TetherService extends Service {
            return SubscriptionManager.getActiveDataSubscriptionId();
        }
    }

    @VisibleForTesting
    Resources getResourceForActiveDataSubId() {
        final int subId = getTetherServiceWrapper().getActiveDataSubscriptionId();
        return Utils.getResourcesForSubId(this, subId);
    }
}
+8 −6
Original line number Diff line number Diff line
@@ -18,9 +18,10 @@ package com.android.settings.network;

import static android.net.TetheringConstants.EXTRA_ADD_TETHER_TYPE;
import static android.net.TetheringConstants.EXTRA_PROVISION_CALLBACK;
import static android.net.TetheringConstants.EXTRA_RUN_PROVISION;
import static android.net.TetheringManager.TETHERING_WIFI;

import static com.android.settings.network.TetherProvisioningActivity.EXTRA_TETHER_SUBID;
import static com.android.settings.network.TetherProvisioningActivity.EXTRA_TETHER_UI_PROVISIONING_APP_NAME;
import static com.android.settings.network.TetherProvisioningActivity.PROVISION_REQUEST;

import static org.junit.Assert.assertEquals;
@@ -72,7 +73,7 @@ public class TetherProvisioningActivityTest {
                new Intent(Settings.ACTION_TETHER_PROVISIONING_UI)
                        .putExtra(EXTRA_ADD_TETHER_TYPE, TETHERING_WIFI)
                        .putExtra(EXTRA_PROVISION_CALLBACK, receiver)
                        .putExtra(TetherProvisioningActivity.EXTRA_SUBID, 10000))) {
                        .putExtra(TetherProvisioningActivity.EXTRA_TETHER_SUBID, 10000))) {
            assertEquals(TetheringManager.TETHER_ERROR_PROVISIONING_FAILED, receiver.get());
            assertEquals(Lifecycle.State.DESTROYED, scenario.getState());
        }
@@ -82,12 +83,13 @@ public class TetherProvisioningActivityTest {
    public void testOnCreate_FinishWithUnavailableProvisioningApp() throws Exception {
        final WrappedReceiver receiver = new WrappedReceiver();
        final int subId = SubscriptionManager.getActiveDataSubscriptionId();
        final String[] emptyProvisioningApp = { "", "" };
        try (ActivityScenario<TetherProvisioningActivity> scenario = ActivityScenario.launch(
                new Intent(Settings.ACTION_TETHER_PROVISIONING_UI)
                        .putExtra(EXTRA_ADD_TETHER_TYPE, TETHERING_WIFI)
                        .putExtra(EXTRA_PROVISION_CALLBACK, receiver)
                        .putExtra(TetherProvisioningActivity.EXTRA_SUBID, subId)
                        .putExtra(EXTRA_RUN_PROVISION, new String[] { "", "" }))) {
                        .putExtra(EXTRA_TETHER_SUBID, subId)
                        .putExtra(EXTRA_TETHER_UI_PROVISIONING_APP_NAME, emptyProvisioningApp))) {
            assertEquals(TetheringManager.TETHER_ERROR_PROVISIONING_FAILED, receiver.get());
            assertEquals(Lifecycle.State.DESTROYED, scenario.getState());
        }
@@ -105,8 +107,8 @@ public class TetherProvisioningActivityTest {
                new Intent(Settings.ACTION_TETHER_PROVISIONING_UI)
                        .putExtra(EXTRA_ADD_TETHER_TYPE, TETHERING_WIFI)
                        .putExtra(EXTRA_PROVISION_CALLBACK, receiver)
                        .putExtra(TetherProvisioningActivity.EXTRA_SUBID, subId)
                        .putExtra(EXTRA_RUN_PROVISION, provisionApp))) {
                        .putExtra(EXTRA_TETHER_SUBID, subId)
                        .putExtra(EXTRA_TETHER_UI_PROVISIONING_APP_NAME, provisionApp))) {
            scenario.onActivity(activity -> {
                assertFalse(activity.isFinishing());
                activity.onActivityResult(PROVISION_REQUEST, Activity.RESULT_OK, null /* intent */);
+10 −2
Original line number Diff line number Diff line
@@ -27,6 +27,10 @@ import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
import static android.net.TetheringManager.TETHER_ERROR_PROVISIONING_FAILED;
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;

import static com.android.settings.wifi.tether.TetherService.EXTRA_TETHER_PROVISIONING_RESPONSE;
import static com.android.settings.wifi.tether.TetherService.EXTRA_TETHER_SILENT_PROVISIONING_ACTION;
import static com.android.settings.wifi.tether.TetherService.EXTRA_TETHER_SUBID;

import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.verify;
@@ -228,8 +232,10 @@ public class TetherServiceTest extends ServiceTestCase<TetherService> {
        Intent intent = new Intent();
        intent.putExtra(EXTRA_ADD_TETHER_TYPE, TETHERING_WIFI);
        intent.putExtra(EXTRA_RUN_PROVISION, true);
        intent.putExtra(EXTRA_TETHER_SILENT_PROVISIONING_ACTION, TEST_NO_UI_ACTION);
        intent.putExtra(EXTRA_PROVISION_CALLBACK, mResultReceiver);
        intent.putExtra(TetherService.EXTRA_SUBID, 1 /* Tested subId number */);
        intent.putExtra(EXTRA_TETHER_SUBID, 1 /* Tested subId number */);
        intent.putExtra(EXTRA_TETHER_PROVISIONING_RESPONSE, TEST_RESPONSE_ACTION);
        startService(intent);

        SystemClock.sleep(PROVISION_TIMEOUT);
@@ -242,8 +248,10 @@ public class TetherServiceTest extends ServiceTestCase<TetherService> {
        Intent intent = new Intent();
        intent.putExtra(EXTRA_ADD_TETHER_TYPE, type);
        intent.putExtra(EXTRA_RUN_PROVISION, true);
        intent.putExtra(EXTRA_TETHER_SILENT_PROVISIONING_ACTION, TEST_NO_UI_ACTION);
        intent.putExtra(EXTRA_PROVISION_CALLBACK, mResultReceiver);
        intent.putExtra(TetherService.EXTRA_SUBID, INVALID_SUBSCRIPTION_ID);
        intent.putExtra(EXTRA_TETHER_SUBID, INVALID_SUBSCRIPTION_ID);
        intent.putExtra(EXTRA_TETHER_PROVISIONING_RESPONSE, TEST_RESPONSE_ACTION);
        startService(intent);
    }