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

Commit 2e7baed8 authored by Tim Schumacher's avatar Tim Schumacher Committed by Luca Stefani
Browse files

SystemUI: Add ADB over network tile



Author: Danesh M <daneshm90@gmail.com>
Date:   Fri Jan 23 11:57:52 2015 -0800

    SystemUI: Add adb over network tile

    Change-Id: Ib1fa0c87562ff3a077bf9c7283ce81fc4a8271db

Author: Joey <joey@lineageos.org>
Date:   Mon Jun 25 23:47:39 2018 +0200

    SystemUI: require auth for adb wireless

    Change-Id: I246a0310f0015862b750aa73ed2b546ef6658c8b
    Signed-off-by: default avatarJoey <joey@lineageos.org>

Author: Jason Edson <jaysonedson@gmail.com>
Date:   Sun Sep 2 08:59:39 2018 +0100
Edit:   Updated drawable to make it look like stock AOSP
        and added the host address as secondary text.

Author: Bruno Martins <bgcngm@gmail.com>
Date:   Tue Sep 4 23:33:06 2018 +0100

    SystemUI: Fix several issues in the ADB over Network tile

     * Prior to this change, it was possible to toggle the tile in certain
       circumstances that made no sense at all. Ensure that ADB is globally
       enabled and that there's an active WiFi connection, before switching
       to enabled status.

    Change-Id: Icd5491faf65e838a3d671511cf4dc9e61a39dbde

Author: Sam Mortimer <sam@mortimer.me.uk>
Date:   Tue Jun 4 02:07:25 2019 -0700

    fw/b: Allow adb over network when any default network is active

    * Track the android default network instead of wifi state.

    * If on, always allow toggle off regardless of whether the
      network disappears on you.

    * When toggled on and network has gone show "no network"
      in place of the local link address.

    Change-Id: Ib8ee1b5334ed7409319f79716047b438a7bface8

Change-Id: I07050641c4bb8ad3f398f840e2994131b4393149
parent e2c4a01e
Loading
Loading
Loading
Loading
+34 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
    Copyright (C) 2015 The CyanogenMod Open Source Project
    Copyright (C) 2017 The LineageOS Project

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="64dp"
        android:height="64dp"
        android:viewportWidth="48"
        android:viewportHeight="48">

    <path
        android:fillColor="#FFFFFF"
        android:pathData="M24,43.5l23.3-29c-0.9-0.7-9.9-8-23.3-8c-13.4,0-22.4,7.3-23.3,8L24,43.5L24,43.5
C24,43.5,24,43.5,24,43.5Z
M31.7,16.2c1.4,1.7,2.3,3.9,2.3,6.3v2H14v-2c0-2.4,0.9-4.6,2.3-6.3L14,13.9l1.4-1.4l2.3,2.3
c1.7-1.4,3.9-2.3,6.3-2.3c2.4,0,4.6,0.9,6.3,2.3l2.3-2.3l1.4,1.4L31.7,16.2z
M22,20.5c0,1.1-0.9,2-2,2c-1.1,0-2-0.9-2-2
c0-1.1,0.9-2,2-2C21.1,18.5,22,19.4,22,20.5z
M30,20.5c0,1.1-0.9,2-2,2c-1.1,0-2-0.9-2-2c0-1.1,0.9-2,2-2C29.1,18.5,30,19.4,30,20.5
z" />
</vector>
+5 −1
Original line number Diff line number Diff line
@@ -2,7 +2,7 @@
<!--
/**
 * Copyright (c) 2015, The CyanogenMod Project
 * Copyright (c) 2017-2018, The LineageOS Project
 * Copyright (c) 2017-2019, The LineageOS Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
@@ -41,6 +41,10 @@
    <string name="global_action_current_user">Current</string>

    <!-- Custom QS tiles -->
    <!-- ADB over network QS tile -->
    <string name="quick_settings_network_adb_label">ADB over network</string>
    <string name="quick_settings_network_adb_no_network">no network</string>

    <!-- Caffeine QS tile -->
    <string name="quick_settings_caffeine_label">Caffeine</string>
    <string name="accessibility_quick_settings_caffeine_off">Caffeine off.</string>
+1 −1
Original line number Diff line number Diff line
@@ -117,7 +117,7 @@

    <!-- Tiles native to System UI. Order should match "quick_settings_tiles_default" -->
    <string name="quick_settings_tiles_stock" translatable="false">
        wifi,cell,battery,dnd,flashlight,rotation,bt,airplane,nfc,location,hotspot,inversion,saver,dark,work,cast,night,caffeine,heads_up,sync,volume_panel
        wifi,cell,battery,dnd,flashlight,rotation,bt,airplane,nfc,location,hotspot,inversion,saver,dark,work,cast,night,adb_network,caffeine,heads_up,sync,volume_panel
    </string>

    <!-- The tiles to display in QuickSettings -->
+6 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.qs.QSTileView;
import com.android.systemui.qs.QSTileHost;
import com.android.systemui.qs.external.CustomTile;
import com.android.systemui.qs.tiles.AdbOverNetworkTile;
import com.android.systemui.qs.tiles.AirplaneModeTile;
import com.android.systemui.qs.tiles.BatterySaverTile;
import com.android.systemui.qs.tiles.BluetoothTile;
@@ -80,6 +81,7 @@ public class QSFactoryImpl implements QSFactory {
    private final Provider<NfcTile> mNfcTileProvider;
    private final Provider<GarbageMonitor.MemoryTile> mMemoryTileProvider;
    private final Provider<UiModeNightTile> mUiModeNightTileProvider;
    private final Provider<AdbOverNetworkTile> mAdbOverNetworkTileProvider;
    private final Provider<CaffeineTile> mCaffeineTileProvider;
    private final Provider<HeadsUpTile> mHeadsUpTileProvider;
    private final Provider<SyncTile> mSyncTileProvider;
@@ -107,6 +109,7 @@ public class QSFactoryImpl implements QSFactory {
            Provider<NfcTile> nfcTileProvider,
            Provider<GarbageMonitor.MemoryTile> memoryTileProvider,
            Provider<UiModeNightTile> uiModeNightTileProvider,
            Provider<AdbOverNetworkTile> adbOverNetworkTileProvider,
            Provider<CaffeineTile> caffeineTileProvider,
            Provider<HeadsUpTile> headsUpTileProvider,
            Provider<SyncTile> syncTileProvider,
@@ -130,6 +133,7 @@ public class QSFactoryImpl implements QSFactory {
        mNfcTileProvider = nfcTileProvider;
        mMemoryTileProvider = memoryTileProvider;
        mUiModeNightTileProvider = uiModeNightTileProvider;
        mAdbOverNetworkTileProvider = adbOverNetworkTileProvider;
        mCaffeineTileProvider = caffeineTileProvider;
        mHeadsUpTileProvider = headsUpTileProvider;
        mSyncTileProvider = syncTileProvider;
@@ -188,6 +192,8 @@ public class QSFactoryImpl implements QSFactory {
            case "dark":
                return mUiModeNightTileProvider.get();
            // Custom tiles.
            case "adb_network":
                return mAdbOverNetworkTileProvider.get();
            case "caffeine":
                return mCaffeineTileProvider.get();
            case "heads_up":
+207 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2015 The CyanogenMod Project
 * Copyright (C) 2017-2019 The LineageOS Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.qs.tiles;

import android.content.Context;
import android.content.Intent;
import android.database.ContentObserver;
import android.net.ConnectivityManager;
import android.net.LinkAddress;
import android.net.Network;
import android.net.Uri;
import android.os.UserHandle;
import android.provider.Settings;
import android.service.quicksettings.Tile;

import com.android.systemui.Dependency;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.QSTile.BooleanState;
import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.R;
import com.android.systemui.statusbar.policy.KeyguardMonitor;

import lineageos.providers.LineageSettings;
import org.lineageos.internal.logging.LineageMetricsLogger;

import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.util.List;

import javax.inject.Inject;

/** Quick settings tile: AdbOverNetwork **/
public class AdbOverNetworkTile extends QSTileImpl<BooleanState> {

    private boolean mListening;
    private final KeyguardMonitor mKeyguardMonitor;
    private final KeyguardMonitorCallback mKeyguardCallback = new KeyguardMonitorCallback();

    private final ConnectivityManager mConnectivityManager;

    private String mNetworkAddress;

    private static final Intent SETTINGS_DEVELOPMENT =
            new Intent(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS);

    @Inject
    public AdbOverNetworkTile(QSHost host) {
        super(host);
        mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
        mConnectivityManager = mContext.getSystemService(ConnectivityManager.class);
    }

    @Override
    public BooleanState newTileState() {
        return new BooleanState();
    }

    @Override
    protected void handleClick() {
        if (mKeyguardMonitor.isSecure() && !mKeyguardMonitor.canSkipBouncer()) {
            Dependency.get(ActivityStarter.class)
                    .postQSRunnableDismissingKeyguard(this::toggleAction);
        } else {
            toggleAction();
        }
    }

    @Override
    public Intent getLongClickIntent() {
        return SETTINGS_DEVELOPMENT;
    }

    @Override
    protected void handleUpdateState(BooleanState state, Object arg) {
        state.value = isAdbEnabled() && isAdbNetworkEnabled();
        state.icon = ResourceIcon.get(R.drawable.ic_qs_network_adb);
        state.label = mContext.getString(R.string.quick_settings_network_adb_label);
        if (state.value) {
            state.secondaryLabel = mNetworkAddress != null ? mNetworkAddress
                    : mContext.getString(R.string.quick_settings_network_adb_no_network);
            state.state = Tile.STATE_ACTIVE;
        } else {
            state.secondaryLabel = null;
            state.state = canEnableAdbNetwork() ? Tile.STATE_INACTIVE : Tile.STATE_UNAVAILABLE;
        }
    }

    @Override
    public CharSequence getTileLabel() {
        return mContext.getString(R.string.quick_settings_network_adb_label);
    }

    @Override
    public int getMetricsCategory() {
        return LineageMetricsLogger.TILE_ADB_OVER_NETWORK;
    }

    private boolean isAdbEnabled() {
        return Settings.Global.getInt(mContext.getContentResolver(),
                Settings.Global.ADB_ENABLED, 0) > 0;
    }

    private boolean isAdbNetworkEnabled() {
        return LineageSettings.Secure.getInt(mContext.getContentResolver(),
                LineageSettings.Secure.ADB_PORT, 0) > 0;
    }

    private boolean canEnableAdbNetwork() {
        return isAdbEnabled() && isNetworkAvailable();
    }

    private boolean isNetworkAvailable() {
        return mNetworkAddress != null;
    }

    private void toggleAction() {
        final boolean active = getState().value;
        // Always allow toggle off if currently on.
        if (!active && !canEnableAdbNetwork()) {
            return;
        }
        LineageSettings.Secure.putIntForUser(mContext.getContentResolver(),
                LineageSettings.Secure.ADB_PORT, active ? -1 : 5555,
                UserHandle.USER_CURRENT);
    }

    private ContentObserver mObserver = new ContentObserver(mHandler) {
        @Override
        public void onChange(boolean selfChange, Uri uri) {
            refreshState();
        }
    };

    @Override
    public void handleSetListening(boolean listening) {
        if (mListening != listening) {
            mListening = listening;
            if (listening) {
                mContext.getContentResolver().registerContentObserver(
                        LineageSettings.Secure.getUriFor(LineageSettings.Secure.ADB_PORT),
                        false, mObserver);
                mContext.getContentResolver().registerContentObserver(
                        Settings.Global.getUriFor(Settings.Global.ADB_ENABLED),
                        false, mObserver);
                mKeyguardMonitor.addCallback(mKeyguardCallback);
                mConnectivityManager.registerDefaultNetworkCallback(mNetworkCallback);
            } else {
                mContext.getContentResolver().unregisterContentObserver(mObserver);
                mKeyguardMonitor.removeCallback(mKeyguardCallback);
                mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
            }
        }
    }

    private class KeyguardMonitorCallback implements KeyguardMonitor.Callback {
        @Override
        public void onKeyguardShowingChanged() {
            refreshState();
        }
    }

    private ConnectivityManager.NetworkCallback mNetworkCallback =
            new ConnectivityManager.NetworkCallback() {
        @Override
        public void onAvailable(Network network) {
            List<LinkAddress> linkAddresses =
                    mConnectivityManager.getLinkProperties(network).getLinkAddresses();
            // Determine local network address.
            // Use first IPv4 address if available, otherwise use first IPv6.
            String ipv4 = null, ipv6 = null;
            for (LinkAddress la : linkAddresses) {
                final InetAddress addr = la.getAddress();
                if (ipv4 == null && addr instanceof Inet4Address) {
                    ipv4 = addr.getHostAddress();
                    break;
                } else if (ipv6 == null && addr instanceof Inet6Address) {
                    ipv6 = addr.getHostAddress();
                }
            }
            mNetworkAddress = ipv4 != null ? ipv4 : ipv6;
            refreshState();
        }

        @Override
        public void onLost(Network network) {
            mNetworkAddress = null;
            refreshState();
        }
    };
}