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

Commit 35bd30b1 authored by Wink Saville's avatar Wink Saville Committed by Android (Google) Code Review
Browse files

Merge "Merge commit '270226b0' into manualmerge" into klp-dev

parents 79a45c6f 7788c61a
Loading
Loading
Loading
Loading
+27 −95
Original line number Diff line number Diff line
@@ -16,22 +16,16 @@

package android.net;

import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.net.ConnectivityManager;
import android.net.IConnectivityManager;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Handler;
import android.os.UserHandle;
import android.os.Message;
import android.os.RemoteException;
import android.os.SystemClock;
@@ -46,7 +40,6 @@ import android.telephony.CellInfoGsm;
import android.telephony.CellInfoLte;
import android.telephony.CellInfoWcdma;
import android.telephony.TelephonyManager;
import android.text.TextUtils;

import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
@@ -60,8 +53,6 @@ import java.net.URL;
import java.net.UnknownHostException;
import java.util.List;

import com.android.internal.R;

/**
 * This class allows captive portal detection on a network.
 * @hide
@@ -71,7 +62,6 @@ public class CaptivePortalTracker extends StateMachine {
    private static final String TAG = "CaptivePortalTracker";

    private static final String DEFAULT_SERVER = "clients3.google.com";
    private static final String NOTIFICATION_ID = "CaptivePortal.Notification";

    private static final int SOCKET_TIMEOUT_MS = 10000;

@@ -93,7 +83,6 @@ public class CaptivePortalTracker extends StateMachine {

    private String mServer;
    private String mUrl;
    private boolean mNotificationShown = false;
    private boolean mIsCaptivePortalCheckEnabled = false;
    private IConnectivityManager mConnService;
    private TelephonyManager mTelephonyManager;
@@ -192,12 +181,12 @@ public class CaptivePortalTracker extends StateMachine {
    private class DefaultState extends State {
        @Override
        public void enter() {
            if (DBG) log(getName() + "\n");
            setNotificationOff();
        }

        @Override
        public boolean processMessage(Message message) {
            if (DBG) log(getName() + message.toString() + "\n");
            if (DBG) log(getName() + message.toString());
            switch (message.what) {
                case CMD_DETECT_PORTAL:
                    NetworkInfo info = (NetworkInfo) message.obj;
@@ -219,24 +208,25 @@ public class CaptivePortalTracker extends StateMachine {
    private class NoActiveNetworkState extends State {
        @Override
        public void enter() {
            if (DBG) log(getName() + "\n");
            mNetworkInfo = null;
            /* Clear any previous notification */
            setNotificationVisible(false);
        }

        @Override
        public boolean processMessage(Message message) {
            if (DBG) log(getName() + message.toString() + "\n");
            if (DBG) log(getName() + message.toString());
            InetAddress server;
            NetworkInfo info;
            switch (message.what) {
                case CMD_CONNECTIVITY_CHANGE:
                    info = (NetworkInfo) message.obj;
                    if (info.getType() == ConnectivityManager.TYPE_WIFI) {
                        if (info.isConnected() && isActiveNetwork(info)) {
                            mNetworkInfo = info;
                            transitionTo(mDelayedCaptiveCheckState);
                        }
                    } else {
                        log(getName() + " not a wifi connectivity change, ignore");
                    }
                    break;
                default:
                    return NOT_HANDLED;
@@ -248,7 +238,7 @@ public class CaptivePortalTracker extends StateMachine {
    private class ActiveNetworkState extends State {
        @Override
        public void enter() {
            if (DBG) log(getName() + "\n");
            setNotificationOff();
        }

        @Override
@@ -281,7 +271,6 @@ public class CaptivePortalTracker extends StateMachine {
    private class DelayedCaptiveCheckState extends State {
        @Override
        public void enter() {
            if (DBG) log(getName() + "\n");
            Message message = obtainMessage(CMD_DELAYED_CAPTIVE_CHECK, ++mDelayedCheckToken, 0);
            if (mDeviceProvisioned) {
                sendMessageDelayed(message, DELAYED_CHECK_INTERVAL_MS);
@@ -292,7 +281,7 @@ public class CaptivePortalTracker extends StateMachine {

        @Override
        public boolean processMessage(Message message) {
            if (DBG) log(getName() + message.toString() + "\n");
            if (DBG) log(getName() + message.toString());
            switch (message.what) {
                case CMD_DELAYED_CAPTIVE_CHECK:
                    if (message.arg1 == mDelayedCheckToken) {
@@ -308,7 +297,12 @@ public class CaptivePortalTracker extends StateMachine {
                            if (captive) {
                                // Setup Wizard will assist the user in connecting to a captive
                                // portal, so make the notification visible unless during setup
                                setNotificationVisible(true);
                                try {
                                    mConnService.setProvisioningNotificationVisible(true,
                                        mNetworkInfo.getType(), mNetworkInfo.getExtraInfo(), mUrl);
                                } catch(RemoteException e) {
                                    e.printStackTrace();
                                }
                            }
                        } else {
                            Intent intent = new Intent(
@@ -366,6 +360,15 @@ public class CaptivePortalTracker extends StateMachine {
        return false;
    }

    private void setNotificationOff() {
        try {
            mConnService.setProvisioningNotificationVisible(false, ConnectivityManager.TYPE_NONE,
                    null, null);
        } catch (RemoteException e) {
            log("setNotificationOff: " + e);
        }
    }

    /**
     * Do a URL fetch on a known server to see if we get the data we expect.
     * Measure the response time and broadcast that.
@@ -435,77 +438,6 @@ public class CaptivePortalTracker extends StateMachine {
        return null;
    }

    private void setNotificationVisible(boolean visible) {
        // if it should be hidden and it is already hidden, then noop
        if (!visible && !mNotificationShown) {
            if (DBG) log("setNotivicationVisible: false and not shown, so noop");
            return;
        }

        Resources r = Resources.getSystem();
        NotificationManager notificationManager = (NotificationManager) mContext
            .getSystemService(Context.NOTIFICATION_SERVICE);

        if (visible) {
            CharSequence title;
            CharSequence details;
            int icon;
            String url = null;
            switch (mNetworkInfo.getType()) {
                case ConnectivityManager.TYPE_WIFI:
                    title = r.getString(R.string.wifi_available_sign_in, 0);
                    details = r.getString(R.string.network_available_sign_in_detailed,
                            mNetworkInfo.getExtraInfo());
                    icon = R.drawable.stat_notify_wifi_in_range;
                    url = mUrl;
                    break;
                case ConnectivityManager.TYPE_MOBILE:
                    title = r.getString(R.string.network_available_sign_in, 0);
                    // TODO: Change this to pull from NetworkInfo once a printable
                    // name has been added to it
                    details = mTelephonyManager.getNetworkOperatorName();
                    icon = R.drawable.stat_notify_rssi_in_range;
                    try {
                        url = mConnService.getMobileProvisioningUrl();
                        if (TextUtils.isEmpty(url)) {
                            url = mConnService.getMobileRedirectedProvisioningUrl();
                        }
                    } catch(RemoteException e) {
                        e.printStackTrace();
                    }
                    if (TextUtils.isEmpty(url)) {
                        url = mUrl;
                    }
                    break;
                default:
                    title = r.getString(R.string.network_available_sign_in, 0);
                    details = r.getString(R.string.network_available_sign_in_detailed,
                            mNetworkInfo.getExtraInfo());
                    icon = R.drawable.stat_notify_rssi_in_range;
                    url = mUrl;
                    break;
            }

            Notification notification = new Notification();
            notification.when = 0;
            notification.icon = icon;
            notification.flags = Notification.FLAG_AUTO_CANCEL;
            Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
            intent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT |
                    Intent.FLAG_ACTIVITY_NEW_TASK);
            notification.contentIntent = PendingIntent.getActivity(mContext, 0, intent, 0);
            notification.tickerText = title;
            notification.setLatestEventInfo(mContext, title, details, notification.contentIntent);

            if (DBG) log("setNotivicationVisible: make visible");
            notificationManager.notify(NOTIFICATION_ID, 1, notification);
        } else {
            if (DBG) log("setNotivicationVisible: cancel notification");
            notificationManager.cancel(NOTIFICATION_ID, 1);
        }
        mNotificationShown = visible;
    }

    private void sendFailedCaptivePortalCheckBroadcast(long requestTimestampMs) {
        sendNetworkConditionsBroadcast(false /* response received */, false /* ignored */,
                requestTimestampMs, 0 /* ignored */);
+42 −47
Original line number Diff line number Diff line
@@ -623,6 +623,29 @@ public class ConnectivityManager {
        }
    }

    /**
     * Returns details about the Provisioning or currently active default data network. When
     * connected, this network is the default route for outgoing connections.
     * You should always check {@link NetworkInfo#isConnected()} before initiating
     * network traffic. This may return {@code null} when there is no default
     * network.
     *
     * @return a {@link NetworkInfo} object for the current default network
     *        or {@code null} if no network default network is currently active
     *
     * <p>This method requires the call to hold the permission
     * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}.
     *
     * {@hide}
     */
    public NetworkInfo getProvisioningOrActiveNetworkInfo() {
        try {
            return mService.getProvisioningOrActiveNetworkInfo();
        } catch (RemoteException e) {
            return null;
        }
    }

    /**
     * Returns the IP information for the current default network.
     *
@@ -1357,63 +1380,19 @@ public class ConnectivityManager {
    }

    /**
     * The ResultReceiver resultCode for checkMobileProvisioning (CMP_RESULT_CODE)
     */

    /**
     * No connection was possible to the network.
     * {@hide}
     */
    public static final int CMP_RESULT_CODE_NO_CONNECTION = 0;

    /**
     * A connection was made to the internet, all is well.
     * {@hide}
     */
    public static final int CMP_RESULT_CODE_CONNECTABLE = 1;

    /**
     * A connection was made but there was a redirection, we appear to be in walled garden.
     * This is an indication of a warm sim on a mobile network.
     * {@hide}
     */
    public static final int CMP_RESULT_CODE_REDIRECTED = 2;

    /**
     * A connection was made but no dns server was available to resolve a name to address.
     * This is an indication of a warm sim on a mobile network.
     * Check mobile provisioning.
     *
     * {@hide}
     */
    public static final int CMP_RESULT_CODE_NO_DNS = 3;

    /**
     * A connection was made but could not open a TCP connection.
     * This is an indication of a warm sim on a mobile network.
     * {@hide}
     */
    public static final int CMP_RESULT_CODE_NO_TCP_CONNECTION = 4;

    /**
     * Check mobile provisioning. The resultCode passed to
     * onReceiveResult will be one of the CMP_RESULT_CODE_xxxx values above.
     * This may take a minute or more to complete.
     *
     * @param sendNotificaiton, when true a notification will be sent to user.
     * @param suggestedTimeOutMs, timeout in milliseconds
     * @param resultReceiver needs to  be supplied to receive the result
     *
     * @return time out that will be used, maybe less that suggestedTimeOutMs
     * -1 if an error.
     *
     * {@hide}
     */
    public int checkMobileProvisioning(boolean sendNotification, int suggestedTimeOutMs,
            ResultReceiver resultReceiver) {
    public int checkMobileProvisioning(int suggestedTimeOutMs) {
        int timeOutMs = -1;
        try {
            timeOutMs = mService.checkMobileProvisioning(sendNotification, suggestedTimeOutMs,
                    resultReceiver);
            timeOutMs = mService.checkMobileProvisioning(suggestedTimeOutMs);
        } catch (RemoteException e) {
        }
        return timeOutMs;
@@ -1481,4 +1460,20 @@ public class ConnectivityManager {
            return null;
        }
    }

    /**
     * Set sign in error notification to visible or in visible
     *
     * @param visible
     * @param networkType
     *
     * {@hide}
     */
    public void setProvisioningNotificationVisible(boolean visible, int networkType,
            String extraInfo, String url) {
        try {
            mService.setProvisioningNotificationVisible(visible, networkType, extraInfo, url);
        } catch (RemoteException e) {
        }
    }
}
+4 −1
Original line number Diff line number Diff line
@@ -50,6 +50,8 @@ interface IConnectivityManager
    NetworkInfo getNetworkInfo(int networkType);
    NetworkInfo[] getAllNetworkInfo();

    NetworkInfo getProvisioningOrActiveNetworkInfo();

    boolean isNetworkSupported(int networkType);

    LinkProperties getActiveLinkProperties();
@@ -141,7 +143,7 @@ interface IConnectivityManager

    int findConnectionTypeForIface(in String iface);

    int checkMobileProvisioning(boolean sendNotification, int suggestedTimeOutMs, in ResultReceiver resultReceiver);
    int checkMobileProvisioning(int suggestedTimeOutMs);

    String getMobileProvisioningUrl();

@@ -153,4 +155,5 @@ interface IConnectivityManager

    LinkInfo[] getAllLinkInfo();

    void setProvisioningNotificationVisible(boolean visible, int networkType, in String extraInfo, in String url);
}
+80 −14
Original line number Diff line number Diff line
@@ -61,8 +61,12 @@ public class MobileDataStateTracker extends BaseNetworkStateTracker {
    private ITelephony mPhoneService;

    private String mApnType;
    private NetworkInfo mNetworkInfo;
    private boolean mTeardownRequested = false;
    private Handler mTarget;
    private Context mContext;
    private LinkProperties mLinkProperties;
    private LinkCapabilities mLinkCapabilities;
    private boolean mPrivateDnsRouteSet = false;
    private boolean mDefaultRouteSet = false;

@@ -106,6 +110,7 @@ public class MobileDataStateTracker extends BaseNetworkStateTracker {

        IntentFilter filter = new IntentFilter();
        filter.addAction(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
        filter.addAction(TelephonyIntents.ACTION_DATA_CONNECTION_CONNECTED_TO_PROVISIONING_APN);
        filter.addAction(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED);

        mContext.registerReceiver(new MobileDataStateReceiver(), filter);
@@ -184,10 +189,41 @@ public class MobileDataStateTracker extends BaseNetworkStateTracker {
    public void releaseWakeLock() {
    }

    private void updateLinkProperitesAndCapatilities(Intent intent) {
        mLinkProperties = intent.getParcelableExtra(
                PhoneConstants.DATA_LINK_PROPERTIES_KEY);
        if (mLinkProperties == null) {
            loge("CONNECTED event did not supply link properties.");
            mLinkProperties = new LinkProperties();
        }
        mLinkCapabilities = intent.getParcelableExtra(
                PhoneConstants.DATA_LINK_CAPABILITIES_KEY);
        if (mLinkCapabilities == null) {
            loge("CONNECTED event did not supply link capabilities.");
            mLinkCapabilities = new LinkCapabilities();
        }
    }

    private class MobileDataStateReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(TelephonyIntents.
                    ACTION_DATA_CONNECTION_CONNECTED_TO_PROVISIONING_APN)) {
                String apnName = intent.getStringExtra(PhoneConstants.DATA_APN_KEY);
                String apnType = intent.getStringExtra(PhoneConstants.DATA_APN_TYPE_KEY);
                if (!TextUtils.equals(mApnType, apnType)) {
                    return;
                }
                if (DBG) {
                    log("Broadcast received: " + intent.getAction() + " apnType=" + apnType
                            + " apnName=" + apnName);
                }

                // Make us in the connecting state until we make a new TYPE_MOBILE_PROVISIONING
                mMobileDataState = PhoneConstants.DataState.CONNECTING;
                updateLinkProperitesAndCapatilities(intent);
                setDetailedState(DetailedState.CONNECTED_TO_PROVISIONING_NETWORK, "", apnName);
            } else if (intent.getAction().equals(TelephonyIntents.
                    ACTION_ANY_DATA_CONNECTION_STATE_CHANGED)) {
                String apnType = intent.getStringExtra(PhoneConstants.DATA_APN_TYPE_KEY);
                if (VDBG) {
@@ -249,18 +285,7 @@ public class MobileDataStateTracker extends BaseNetworkStateTracker {
                            setDetailedState(DetailedState.SUSPENDED, reason, apnName);
                            break;
                        case CONNECTED:
                            mLinkProperties = intent.getParcelableExtra(
                                    PhoneConstants.DATA_LINK_PROPERTIES_KEY);
                            if (mLinkProperties == null) {
                                loge("CONNECTED event did not supply link properties.");
                                mLinkProperties = new LinkProperties();
                            }
                            mLinkCapabilities = intent.getParcelableExtra(
                                    PhoneConstants.DATA_LINK_CAPABILITIES_KEY);
                            if (mLinkCapabilities == null) {
                                loge("CONNECTED event did not supply link capabilities.");
                                mLinkCapabilities = new LinkCapabilities();
                            }
                            updateLinkProperitesAndCapatilities(intent);
                            setDetailedState(DetailedState.CONNECTED, reason, apnName);
                            break;
                    }
@@ -319,8 +344,8 @@ public class MobileDataStateTracker extends BaseNetworkStateTracker {
                String reason = intent.getStringExtra(PhoneConstants.FAILURE_REASON_KEY);
                String apnName = intent.getStringExtra(PhoneConstants.DATA_APN_KEY);
                if (DBG) {
                    log("Received " + intent.getAction() +
                                " broadcast" + (reason == null ? "" : "(" + reason + ")"));
                    log("Broadcast received: " + intent.getAction() +
                                " reason=" + reason == null ? "null" : reason);
                }
                setDetailedState(DetailedState.FAILED, reason, apnName);
            } else {
@@ -412,6 +437,13 @@ public class MobileDataStateTracker extends BaseNetworkStateTracker {
        return (setEnableApn(mApnType, false) != PhoneConstants.APN_REQUEST_FAILED);
    }

    /**
     * @return true if this is ready to operate
     */
    public boolean isReady() {
        return mDataConnectionTrackerAc != null;
    }

    @Override
    public void captivePortalCheckComplete() {
        // not implemented
@@ -574,6 +606,40 @@ public class MobileDataStateTracker extends BaseNetworkStateTracker {
        }
    }

    /**
     *  Inform DCT mobile provisioning has started, it ends when provisioning completes.
     */
    public void enableMobileProvisioning(String url) {
        if (DBG) log("enableMobileProvisioning(url=" + url + ")");
        final AsyncChannel channel = mDataConnectionTrackerAc;
        if (channel != null) {
            Message msg = Message.obtain();
            msg.what = DctConstants.CMD_ENABLE_MOBILE_PROVISIONING;
            msg.setData(Bundle.forPair(DctConstants.PROVISIONING_URL_KEY, url));
            channel.sendMessage(msg);
        }
    }

    /**
     * Return if this network is the provisioning network. Valid only if connected.
     * @param met
     */
    public boolean isProvisioningNetwork() {
        boolean retVal;
        try {
            Message msg = Message.obtain();
            msg.what = DctConstants.CMD_IS_PROVISIONING_APN;
            msg.setData(Bundle.forPair(DctConstants.APN_TYPE_KEY, mApnType));
            Message result = mDataConnectionTrackerAc.sendMessageSynchronously(msg);
            retVal = result.arg1 == DctConstants.ENABLED;
        } catch (NullPointerException e) {
            loge("isProvisioningNetwork: X " + e);
            retVal = false;
        }
        if (DBG) log("isProvisioningNetwork: retVal=" + retVal);
        return retVal;
    }

    @Override
    public void addStackedLink(LinkProperties link) {
        mLinkProperties.addStackedLink(link);
+7 −0
Original line number Diff line number Diff line
@@ -84,6 +84,12 @@ public class NetworkInfo implements Parcelable {
        VERIFYING_POOR_LINK,
        /** Checking if network is a captive portal */
        CAPTIVE_PORTAL_CHECK,
        /**
         * Network is connected to provisioning network
         * TODO: Probably not needed when we add TYPE_PROVISIONING_NETWORK
         * @hide
         */
        CONNECTED_TO_PROVISIONING_NETWORK
    }

    /**
@@ -108,6 +114,7 @@ public class NetworkInfo implements Parcelable {
        stateMap.put(DetailedState.DISCONNECTED, State.DISCONNECTED);
        stateMap.put(DetailedState.FAILED, State.DISCONNECTED);
        stateMap.put(DetailedState.BLOCKED, State.DISCONNECTED);
        stateMap.put(DetailedState.CONNECTED_TO_PROVISIONING_NETWORK, State.CONNECTED);
    }

    private int mNetworkType;
Loading