All Downloads are FREE. Search and download functionalities are using the official Maven repository.

src.com.android.clockwork.connectivity.WearConnectivityController Maven / Gradle / Ivy

package com.android.clockwork.connectivity;

import android.annotation.Nullable;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.SystemClock;
import android.provider.Settings;
import android.util.Log;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.IndentingPrintWriter;
import com.android.clockwork.bluetooth.WearBluetoothMediator;
import com.android.clockwork.cellular.WearCellularMediator;
import com.android.clockwork.common.ActivityModeTracker;
import com.android.clockwork.wifi.WearWifiMediator;

import java.util.concurrent.TimeUnit;

/**
 * WearConnectivityController routes inputs and signals from various sources
 * and relays the appropriate info to the respective WiFi/Cellular Mediators.
 *
 * The WifiMediator is expected to always exist. The BtMediator and CellMediator may be null.
 */
public class WearConnectivityController implements
        ActivityModeTracker.Listener,
        WearNetworkObserver.Listener,
        WearProxyNetworkAgent.Listener {
    private static final String TAG = "WearConnectivity";

    static final String ACTION_PROXY_STATUS_CHANGE =
            "com.android.clockwork.connectivity.action.PROXY_STATUS_CHANGE";
    static final String ACTION_NOTIFY_OFF_BODY_CHANGE =
            "com.google.android.clockwork.connectivity.action.ACTION_NOTIFY_OFF_BODY_CHANGE";

    /**
     * Specifically use a smaller state change delay when transitioning away from BT.
     * This minimizes the duration of the netTransitionWakelock held by ConnectivityService
     * whenever the primary/default network disappears, while still allowing some amount of time
     * for BT to reconnect before we enable wifi.
     *
     * See b/30574433 for more details.
     */
    private static final long DEFAULT_BT_STATE_CHANGE_DELAY_MS = TimeUnit.SECONDS.toMillis(5);
    private static final long MAX_ACCEPTABLE_DELAY_MS = TimeUnit.SECONDS.toMillis(60);

    // dependencies
    private final Context mContext;
    private final AlarmManager mAlarmManager;
    @Nullable private final WearBluetoothMediator mBtMediator;
    @Nullable private final WearCellularMediator mCellMediator;
    private final WearWifiMediator mWifiMediator;
    private final WearProxyNetworkAgent mProxyNetworkAgent;
    private final ActivityModeTracker mActivityModeTracker;

    // params
    private long mBtStateChangeDelayMs;

    // state
    private int mNumWifiRequests = 0;
    private int mNumCellularRequests;
    private int mNumHighBandwidthRequests = 0;
    private int mNumUnmeteredRequests = 0;

    @VisibleForTesting final PendingIntent notifyProxyStatusChangeIntent;
    @VisibleForTesting
    BroadcastReceiver notifyProxyStatusChangeReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (ACTION_PROXY_STATUS_CHANGE.equals(intent.getAction())) {
                notifyProxyStatusChange();
            }
        }
    };

    public WearConnectivityController(
            Context context,
            AlarmManager alarmManager,
            WearBluetoothMediator btMediator,
            WearWifiMediator wifiMediator,
            WearCellularMediator cellMediator,
            WearProxyNetworkAgent proxyNetworkAgent,
            ActivityModeTracker activityModeTracker) {
        mContext = context;
        mAlarmManager = alarmManager;
        mBtMediator = btMediator;
        mWifiMediator = wifiMediator;
        mCellMediator = cellMediator;
        mProxyNetworkAgent = proxyNetworkAgent;
        mProxyNetworkAgent.addListener(this);
        mActivityModeTracker = activityModeTracker;
        mActivityModeTracker.addListener(this);

        mBtStateChangeDelayMs = DEFAULT_BT_STATE_CHANGE_DELAY_MS;

        notifyProxyStatusChangeIntent = PendingIntent.getBroadcast(
                context, 0, new Intent(ACTION_PROXY_STATUS_CHANGE), 0);
    }

    public void onBootCompleted() {
        mContext.registerReceiver(notifyProxyStatusChangeReceiver,
                new IntentFilter(ACTION_PROXY_STATUS_CHANGE));

        if (mBtMediator != null) {
            mBtMediator.onBootCompleted();
        }
        mWifiMediator.onBootCompleted(mProxyNetworkAgent.isProxyConnected());
        if (mCellMediator != null) {
            mCellMediator.onBootCompleted(mProxyNetworkAgent.isProxyConnected());
        }

        if (mActivityModeTracker.isActivityModeEnabled()) {
            onActivityModeChanged(true);
        }
    }

    @VisibleForTesting
    void setBluetoothStateChangeDelay(long delayMs) {
        mBtStateChangeDelayMs = delayMs;
    }

    @Override
    public void onProxyConnectionChange(boolean proxyConnected) {
        mAlarmManager.cancel(notifyProxyStatusChangeIntent);

        // directly notify on connects, or if no delay is configured
        if (proxyConnected || mBtStateChangeDelayMs <= 0) {
            notifyProxyStatusChange();
        } else {
            mAlarmManager.setWindow(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                    SystemClock.elapsedRealtime() + mBtStateChangeDelayMs,
                    MAX_ACCEPTABLE_DELAY_MS,
                    notifyProxyStatusChangeIntent);
        }
    }

    private void notifyProxyStatusChange() {
        mWifiMediator.updateProxyConnected(mProxyNetworkAgent.isProxyConnected());
        if (mCellMediator != null) {
            mCellMediator.updateProxyConnected(mProxyNetworkAgent.isProxyConnected());
        }
    }

    @Override
    public void onUnmeteredRequestsChanged(int numUnmeteredRequests) {
        mNumUnmeteredRequests = numUnmeteredRequests;
        mWifiMediator.updateNumUnmeteredRequests(numUnmeteredRequests);
    }

    @Override
    public void onHighBandwidthRequestsChanged(int numHighBandwidthRequests) {
        mNumHighBandwidthRequests = numHighBandwidthRequests;
        if (mCellMediator != null) {
            mCellMediator.updateNumHighBandwidthRequests(numHighBandwidthRequests);
        }
        mWifiMediator.updateNumHighBandwidthRequests(numHighBandwidthRequests);
    }

    @Override
    public void onWifiRequestsChanged(int numWifiRequests) {
        mNumWifiRequests = numWifiRequests;
        mWifiMediator.updateNumWifiRequests(numWifiRequests);
    }

    @Override
    public void onCellularRequestsChanged(int numCellularRequests) {
        mNumCellularRequests = numCellularRequests;
        if (mCellMediator != null) {
            mCellMediator.updateNumCellularRequests(numCellularRequests);
        }
    }

    @Override
    public void onActivityModeChanged(boolean enabled) {
        if (mActivityModeTracker.affectsBluetooth()) {
            mBtMediator.updateActivityMode(enabled);
        }

        if (mActivityModeTracker.affectsWifi()) {
            mWifiMediator.updateActivityMode(enabled);
        }

        if (mActivityModeTracker.affectsCellular()) {
            mCellMediator.updateActivityMode(enabled);
        }
    }

    public void dump(IndentingPrintWriter ipw) {
        ipw.println("================ WearConnectivityService ================");
        ipw.println("Proxy NetworkAgent connection status:" +
                (mProxyNetworkAgent.isProxyConnected() ? "connected" : "disconnected"));
        mActivityModeTracker.dump(ipw);
        ipw.println();
        ipw.printPair("mNumHighBandwidthRequests", mNumHighBandwidthRequests);
        ipw.printPair("mNumUnmeteredRequests", mNumUnmeteredRequests);
        ipw.printPair("mNumWifiRequests", mNumWifiRequests);
        ipw.printPair("mNumCellularRequests", mNumCellularRequests);
        ipw.println();

        ipw.increaseIndent();

        ipw.println();
        if (mBtMediator != null) {
            mBtMediator.dump(ipw);
        } else {
            ipw.println("Wear Bluetooth disabled because BluetoothAdapter is missing.");
        }

        ipw.println();
        mWifiMediator.dump(ipw);

        ipw.println();
        if (mCellMediator != null) {
            mCellMediator.dump(ipw);
        } else {
            ipw.println("Wear Cellular Mediator disabled on this device.");
        }
        ipw.println();
        ipw.decreaseIndent();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy