blob: a44a6afa551d81d42906b016a6a80fd98e2b87c8 [file] [log] [blame]
package com.android.clockwork.connectivity;
import android.annotation.NonNull;
import android.app.AlarmManager;
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.LinkProperties;
import android.net.NetworkCapabilities;
import android.net.wifi.WifiManager;
import android.os.Binder;
import android.os.Build;
import android.telephony.TelephonyManager;
import com.android.clockwork.bluetooth.BluetoothLogger;
import com.android.clockwork.bluetooth.BluetoothScanModeEnforcer;
import com.android.clockwork.bluetooth.BluetoothShardRunner;
import com.android.clockwork.bluetooth.CompanionTracker;
import com.android.clockwork.bluetooth.WearBluetoothMediator;
import com.android.clockwork.bluetooth.WearBluetoothMediatorSettings;
import com.android.clockwork.bluetooth.proxy.ProxyLinkProperties;
import com.android.clockwork.bluetooth.proxy.ProxyServiceHelper;
import com.android.clockwork.cellular.WearCellularMediator;
import com.android.clockwork.cellular.WearCellularMediatorSettings;
import com.android.clockwork.common.ActivityModeTracker;
import com.android.clockwork.flags.BooleanFlag;
import com.android.clockwork.flags.ClockworkFlags;
import com.android.clockwork.power.PowerTracker;
import com.android.clockwork.power.TimeOnlyMode;
import com.android.clockwork.power.WearPowerServiceInternal;
import com.android.clockwork.wifi.SimpleTimerWifiBackoff;
import com.android.clockwork.wifi.WearWifiMediator;
import com.android.clockwork.wifi.WearWifiMediatorSettings;
import com.android.clockwork.wifi.WifiLogger;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.SystemService;
import java.io.FileDescriptor;
import java.io.PrintWriter;
/**
* WearConnectivityService determines which connectivity mechanisms should be activated
* for a given set of conditions.
*
* Design doc: go/wear-connectivity-service
*/
public class WearConnectivityService extends SystemService {
public static final String SERVICE_NAME = WearConnectivityService.class.getSimpleName();
/** Feature flag for Local Edition/Sino Wear (LE/SW) version. */
@VisibleForTesting static final String FEATURE_CN_GOOGLE = "cn.google";
/** An old feature flag for Local Edition/Sino Wear (LE/SW) version. */
@VisibleForTesting static final String FEATURE_SIDEWINDER = "com.google.sidewinder";
private WearConnectivityController mController;
private BluetoothScanModeEnforcer mBtScanModeEnforcer;
private WearNetworkObserver mWearNetworkObserver;
private BooleanFlag mUserAbsentRadiosOff;
public WearConnectivityService(Context context) {
super(context);
}
@Override
public void onStart() {
publishBinderService(SERVICE_NAME, new BinderService());
}
@Override
public void onBootPhase(int phase) {
if (phase == com.android.server.SystemService.PHASE_SYSTEM_SERVICES_READY) {
mUserAbsentRadiosOff =
ClockworkFlags.userAbsentRadiosOff(getContext().getContentResolver());
WearPowerServiceInternal powerService = getLocalService(WearPowerServiceInternal.class);
PowerTracker powerTracker = powerService.getPowerTracker();
TimeOnlyMode timeOnlyMode = powerService.getTimeOnlyMode();
BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
CompanionTracker companionTracker =
new CompanionTracker(getContext().getContentResolver(), btAdapter);
WearBluetoothMediator btMediator = null;
// btAdapter == null means we're on emulator (or an unsupported device)
if (btAdapter != null) {
BluetoothLogger btLogger = new BluetoothLogger();
mBtScanModeEnforcer =
new BluetoothScanModeEnforcer(getContext(), btAdapter, companionTracker);
ProxyServiceHelper proxyServiceHelper = new ProxyServiceHelper(
getContext(), new NetworkCapabilities(), new ProxyLinkProperties(
new LinkProperties(), isLocalEditionDevice(getContext())));
BluetoothShardRunner btShardRunner =
new BluetoothShardRunner(getContext(), companionTracker,
proxyServiceHelper);
btMediator = new WearBluetoothMediator(
getContext(),
getContext().getSystemService(AlarmManager.class),
new WearBluetoothMediatorSettings(getContext().getContentResolver()),
btAdapter,
btLogger,
btShardRunner,
companionTracker,
powerTracker,
mUserAbsentRadiosOff,
timeOnlyMode);
}
WearCellularMediator cellMediator = null;
PackageManager packageManager = getContext().getPackageManager();
// Don't mediate cell in emulator. The emulator relies on cellular to be present
// and enabled to have the network connectivity required for local/TCP pairing.
if (btAdapter != null
&& packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
TelephonyManager telephonyManager =
getContext().getSystemService(TelephonyManager.class);
cellMediator = new WearCellularMediator(
getContext(),
getContext().getSystemService(AlarmManager.class),
telephonyManager,
new WearCellularMediatorSettings(
getContext(), telephonyManager.getSimOperator()),
powerTracker,
mUserAbsentRadiosOff);
}
WifiLogger wifiLogger = new WifiLogger();
WearWifiMediator wifiMediator = new WearWifiMediator(
getContext(),
getContext().getSystemService(AlarmManager.class),
new WearWifiMediatorSettings(getContext().getContentResolver()),
companionTracker,
powerTracker,
mUserAbsentRadiosOff,
new SimpleTimerWifiBackoff(getContext(), wifiLogger),
getContext().getSystemService(WifiManager.class),
wifiLogger);
WearProxyNetworkAgent proxyNetworkAgent = new WearProxyNetworkAgent(
getContext().getSystemService(ConnectivityManager.class));
mController = new WearConnectivityController(
getContext(),
getContext().getSystemService(AlarmManager.class),
btMediator,
wifiMediator,
cellMediator,
proxyNetworkAgent,
new ActivityModeTracker(getContext()));
mWearNetworkObserver = new WearNetworkObserver(getContext(), mController);
mWearNetworkObserver.register();
} else if (phase == com.android.server.SystemService.PHASE_BOOT_COMPLETED) {
mUserAbsentRadiosOff.register();
mController.onBootCompleted();
}
}
private final class BinderService extends Binder {
@Override
protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
IndentingPrintWriter ipw = new IndentingPrintWriter(writer, " " /* singleIndent */);;
mController.dump(ipw);
ipw.println();
mWearNetworkObserver.dump(ipw);
ipw.println();
if (mBtScanModeEnforcer != null) {
mBtScanModeEnforcer.dump(ipw);
ipw.println();
}
}
}
// Return true if we are running in a special mode for devices in China.
private static boolean isLocalEditionDevice(@NonNull final Context context) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
return false;
}
final PackageManager pm = context.getPackageManager();
return pm.hasSystemFeature(FEATURE_SIDEWINDER)
|| pm.hasSystemFeature(FEATURE_CN_GOOGLE);
}
}