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

Commit b1cb2a2e authored by Tim Schumacher's avatar Tim Schumacher Committed by Michael Bestas
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

Author: Dan Pasanen <dan.pasanen@gmail.com>
    qs: tiles: fix adb over network tile after aaba8ef2

    Change-Id: I4932a3e023a40e362e81fd74f2921e9cb472ebf3
parent 2bbdbb9d
Loading
Loading
Loading
Loading
+34 −0
Original line number Original line 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 Original line Diff line number Diff line
@@ -2,7 +2,7 @@
<!--
<!--
/**
/**
 * Copyright (c) 2015, The CyanogenMod Project
 * 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");
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with 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>
    <string name="global_action_current_user">Current</string>


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


    <!-- Tiles native to System UI. Order should match "quick_settings_tiles_default" -->
    <!-- Tiles native to System UI. Order should match "quick_settings_tiles_default" -->
    <string name="quick_settings_tiles_stock" translatable="false">
    <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>
    </string>


    <!-- The tiles to display in QuickSettings -->
    <!-- The tiles to display in QuickSettings -->
+6 −0
Original line number Original line 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.plugins.qs.QSTileView;
import com.android.systemui.qs.QSTileHost;
import com.android.systemui.qs.QSTileHost;
import com.android.systemui.qs.external.CustomTile;
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.AirplaneModeTile;
import com.android.systemui.qs.tiles.BatterySaverTile;
import com.android.systemui.qs.tiles.BatterySaverTile;
import com.android.systemui.qs.tiles.BluetoothTile;
import com.android.systemui.qs.tiles.BluetoothTile;
@@ -80,6 +81,7 @@ public class QSFactoryImpl implements QSFactory {
    private final Provider<NfcTile> mNfcTileProvider;
    private final Provider<NfcTile> mNfcTileProvider;
    private final Provider<GarbageMonitor.MemoryTile> mMemoryTileProvider;
    private final Provider<GarbageMonitor.MemoryTile> mMemoryTileProvider;
    private final Provider<UiModeNightTile> mUiModeNightTileProvider;
    private final Provider<UiModeNightTile> mUiModeNightTileProvider;
    private final Provider<AdbOverNetworkTile> mAdbOverNetworkTileProvider;
    private final Provider<CaffeineTile> mCaffeineTileProvider;
    private final Provider<CaffeineTile> mCaffeineTileProvider;
    private final Provider<HeadsUpTile> mHeadsUpTileProvider;
    private final Provider<HeadsUpTile> mHeadsUpTileProvider;
    private final Provider<SyncTile> mSyncTileProvider;
    private final Provider<SyncTile> mSyncTileProvider;
@@ -107,6 +109,7 @@ public class QSFactoryImpl implements QSFactory {
            Provider<NfcTile> nfcTileProvider,
            Provider<NfcTile> nfcTileProvider,
            Provider<GarbageMonitor.MemoryTile> memoryTileProvider,
            Provider<GarbageMonitor.MemoryTile> memoryTileProvider,
            Provider<UiModeNightTile> uiModeNightTileProvider,
            Provider<UiModeNightTile> uiModeNightTileProvider,
            Provider<AdbOverNetworkTile> adbOverNetworkTileProvider,
            Provider<CaffeineTile> caffeineTileProvider,
            Provider<CaffeineTile> caffeineTileProvider,
            Provider<HeadsUpTile> headsUpTileProvider,
            Provider<HeadsUpTile> headsUpTileProvider,
            Provider<SyncTile> syncTileProvider,
            Provider<SyncTile> syncTileProvider,
@@ -130,6 +133,7 @@ public class QSFactoryImpl implements QSFactory {
        mNfcTileProvider = nfcTileProvider;
        mNfcTileProvider = nfcTileProvider;
        mMemoryTileProvider = memoryTileProvider;
        mMemoryTileProvider = memoryTileProvider;
        mUiModeNightTileProvider = uiModeNightTileProvider;
        mUiModeNightTileProvider = uiModeNightTileProvider;
        mAdbOverNetworkTileProvider = adbOverNetworkTileProvider;
        mCaffeineTileProvider = caffeineTileProvider;
        mCaffeineTileProvider = caffeineTileProvider;
        mHeadsUpTileProvider = headsUpTileProvider;
        mHeadsUpTileProvider = headsUpTileProvider;
        mSyncTileProvider = syncTileProvider;
        mSyncTileProvider = syncTileProvider;
@@ -188,6 +192,8 @@ public class QSFactoryImpl implements QSFactory {
            case "dark":
            case "dark":
                return mUiModeNightTileProvider.get();
                return mUiModeNightTileProvider.get();
            // Custom tiles.
            // Custom tiles.
            case "adb_network":
                return mAdbOverNetworkTileProvider.get();
            case "caffeine":
            case "caffeine":
                return mCaffeineTileProvider.get();
                return mCaffeineTileProvider.get();
            case "heads_up":
            case "heads_up":
+210 −0
Original line number Original line 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.phone.UnlockMethodCache;
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 UnlockMethodCache mUnlockMethodCache;

    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);
        mUnlockMethodCache = UnlockMethodCache.getInstance(mHost.getContext());
    }

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

    @Override
    protected void handleClick() {
        if (mKeyguardMonitor.isSecure() && !mUnlockMethodCache.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();
        }
    };
}