QuickTileService: Implement and update from VpnService
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
		
							parent
							
								
									d5d3566e6c
								
							
						
					
					
						commit
						416d3adda7
					
				@ -24,7 +24,11 @@
 | 
			
		||||
            android:label="@string/edit_activity_title" />
 | 
			
		||||
        <activity
 | 
			
		||||
            android:name=".SettingsActivity"
 | 
			
		||||
            android:label="@string/settings" />
 | 
			
		||||
            android:label="@string/settings">
 | 
			
		||||
            <intent-filter>
 | 
			
		||||
                <action android:name="android.service.quicksettings.action.QS_TILE_PREFERENCES" />
 | 
			
		||||
            </intent-filter>
 | 
			
		||||
        </activity>
 | 
			
		||||
 | 
			
		||||
        <receiver android:name=".BootCompletedReceiver">
 | 
			
		||||
            <intent-filter>
 | 
			
		||||
@ -32,6 +36,17 @@
 | 
			
		||||
            </intent-filter>
 | 
			
		||||
        </receiver>
 | 
			
		||||
 | 
			
		||||
        <service
 | 
			
		||||
            android:name=".QuickTileService"
 | 
			
		||||
            android:icon="@drawable/ic_tile"
 | 
			
		||||
            android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
 | 
			
		||||
            <intent-filter>
 | 
			
		||||
                <action android:name="android.service.quicksettings.action.QS_TILE" />
 | 
			
		||||
            </intent-filter>
 | 
			
		||||
            <meta-data
 | 
			
		||||
                android:name="android.service.quicksettings.ACTIVE_TILE"
 | 
			
		||||
                android:value="true" />
 | 
			
		||||
        </service>
 | 
			
		||||
        <service
 | 
			
		||||
            android:name=".VpnService"
 | 
			
		||||
            android:exported="false" />
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,81 @@
 | 
			
		||||
package com.wireguard.android;
 | 
			
		||||
 | 
			
		||||
import android.annotation.TargetApi;
 | 
			
		||||
import android.content.ComponentName;
 | 
			
		||||
import android.content.Context;
 | 
			
		||||
import android.content.Intent;
 | 
			
		||||
import android.content.ServiceConnection;
 | 
			
		||||
import android.content.SharedPreferences;
 | 
			
		||||
import android.graphics.drawable.Icon;
 | 
			
		||||
import android.os.Build;
 | 
			
		||||
import android.os.IBinder;
 | 
			
		||||
import android.preference.PreferenceManager;
 | 
			
		||||
import android.service.quicksettings.Tile;
 | 
			
		||||
import android.service.quicksettings.TileService;
 | 
			
		||||
 | 
			
		||||
import com.wireguard.config.Config;
 | 
			
		||||
 | 
			
		||||
@TargetApi(Build.VERSION_CODES.N)
 | 
			
		||||
public class QuickTileService extends TileService {
 | 
			
		||||
    private Config config;
 | 
			
		||||
    private SharedPreferences preferences;
 | 
			
		||||
    private VpnService service;
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onClick() {
 | 
			
		||||
        if (service != null && config != null) {
 | 
			
		||||
            if (config.isEnabled())
 | 
			
		||||
                service.disable(config.getName());
 | 
			
		||||
            else
 | 
			
		||||
                service.enable(config.getName());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onCreate() {
 | 
			
		||||
        preferences = PreferenceManager.getDefaultSharedPreferences(this);
 | 
			
		||||
        service = VpnService.getInstance();
 | 
			
		||||
        if (service == null)
 | 
			
		||||
            bindService(new Intent(this, VpnService.class), new ServiceConnectionCallbacks(),
 | 
			
		||||
                    Context.BIND_AUTO_CREATE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onStartListening() {
 | 
			
		||||
        // Since this is an active tile, this only gets called when we want to update the tile.
 | 
			
		||||
        final Tile tile = getQsTile();
 | 
			
		||||
        final String configName = preferences.getString(VpnService.KEY_PRIMARY_CONFIG, null);
 | 
			
		||||
        config = configName != null && service != null ? service.get(configName) : null;
 | 
			
		||||
        if (config != null) {
 | 
			
		||||
            tile.setLabel(config.getName());
 | 
			
		||||
            final int state = config.isEnabled() ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
 | 
			
		||||
            if (tile.getState() != state) {
 | 
			
		||||
                // The icon must be changed every time the state changes, or the color won't change.
 | 
			
		||||
                final Integer iconResource = (state == Tile.STATE_ACTIVE) ?
 | 
			
		||||
                        R.drawable.ic_tile : R.drawable.ic_tile_disabled;
 | 
			
		||||
                tile.setIcon(Icon.createWithResource(this, iconResource));
 | 
			
		||||
                tile.setState(state);
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            tile.setIcon(Icon.createWithResource(this, R.drawable.ic_tile_disabled));
 | 
			
		||||
            tile.setLabel(getString(R.string.loading));
 | 
			
		||||
            tile.setState(Tile.STATE_UNAVAILABLE);
 | 
			
		||||
        }
 | 
			
		||||
        tile.updateTile();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private class ServiceConnectionCallbacks implements ServiceConnection {
 | 
			
		||||
        @Override
 | 
			
		||||
        public void onServiceConnected(final ComponentName component, final IBinder binder) {
 | 
			
		||||
            // We don't actually need a binding, only notification that the service is started.
 | 
			
		||||
            unbindService(this);
 | 
			
		||||
            service = VpnService.getInstance();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Override
 | 
			
		||||
        public void onServiceDisconnected(final ComponentName component) {
 | 
			
		||||
            // This can never happen; the service runs in the same thread as this service.
 | 
			
		||||
            throw new IllegalStateException();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -1,12 +1,15 @@
 | 
			
		||||
package com.wireguard.android;
 | 
			
		||||
 | 
			
		||||
import android.app.Service;
 | 
			
		||||
import android.content.ComponentName;
 | 
			
		||||
import android.content.Intent;
 | 
			
		||||
import android.content.SharedPreferences;
 | 
			
		||||
import android.os.AsyncTask;
 | 
			
		||||
import android.os.Binder;
 | 
			
		||||
import android.os.Build;
 | 
			
		||||
import android.os.IBinder;
 | 
			
		||||
import android.preference.PreferenceManager;
 | 
			
		||||
import android.service.quicksettings.TileService;
 | 
			
		||||
import android.util.Log;
 | 
			
		||||
 | 
			
		||||
import com.wireguard.config.Config;
 | 
			
		||||
@ -137,11 +140,13 @@ public class VpnService extends Service
 | 
			
		||||
                                          final String key) {
 | 
			
		||||
        if (!KEY_PRIMARY_CONFIG.equals(key))
 | 
			
		||||
            return;
 | 
			
		||||
        boolean changed = false;
 | 
			
		||||
        final String newName = preferences.getString(key, null);
 | 
			
		||||
        if (primaryName != null && !primaryName.equals(newName)) {
 | 
			
		||||
            final Config oldConfig = configurations.get(primaryName);
 | 
			
		||||
            if (oldConfig != null)
 | 
			
		||||
                oldConfig.setIsPrimary(false);
 | 
			
		||||
            changed = true;
 | 
			
		||||
        }
 | 
			
		||||
        if (newName != null && !newName.equals(primaryName)) {
 | 
			
		||||
            final Config newConfig = configurations.get(newName);
 | 
			
		||||
@ -149,8 +154,11 @@ public class VpnService extends Service
 | 
			
		||||
                newConfig.setIsPrimary(true);
 | 
			
		||||
            else
 | 
			
		||||
                preferences.edit().remove(KEY_PRIMARY_CONFIG).apply();
 | 
			
		||||
            changed = true;
 | 
			
		||||
        }
 | 
			
		||||
        primaryName = newName;
 | 
			
		||||
        if (changed)
 | 
			
		||||
            updateTile();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
@ -198,6 +206,13 @@ public class VpnService extends Service
 | 
			
		||||
        new ConfigUpdater(oldConfig, config, wasEnabled).execute();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void updateTile() {
 | 
			
		||||
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N)
 | 
			
		||||
            return;
 | 
			
		||||
        Log.v(TAG, "Requesting quick tile update");
 | 
			
		||||
        TileService.requestListeningState(this, new ComponentName(this, QuickTileService.class));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private class ConfigDisabler extends AsyncTask<Void, Void, Boolean> {
 | 
			
		||||
        private final Config config;
 | 
			
		||||
 | 
			
		||||
@ -219,6 +234,8 @@ public class VpnService extends Service
 | 
			
		||||
            config.setIsEnabled(false);
 | 
			
		||||
            enabledConfigs.remove(config.getName());
 | 
			
		||||
            preferences.edit().putStringSet(KEY_ENABLED_CONFIGS, enabledConfigs).apply();
 | 
			
		||||
            if (config.getName().equals(primaryName))
 | 
			
		||||
                updateTile();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -243,6 +260,8 @@ public class VpnService extends Service
 | 
			
		||||
            config.setIsEnabled(true);
 | 
			
		||||
            enabledConfigs.add(config.getName());
 | 
			
		||||
            preferences.edit().putStringSet(KEY_ENABLED_CONFIGS, enabledConfigs).apply();
 | 
			
		||||
            if (config.getName().equals(primaryName))
 | 
			
		||||
                updateTile();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -18,6 +18,7 @@
 | 
			
		||||
    <string name="hint_optional">(optional)</string>
 | 
			
		||||
    <string name="hint_random">(random)</string>
 | 
			
		||||
    <string name="listen_port">Listen port</string>
 | 
			
		||||
    <string name="loading">Loading</string>
 | 
			
		||||
    <string name="mtu">MTU</string>
 | 
			
		||||
    <string name="placeholder_text">No configuration selected</string>
 | 
			
		||||
    <string name="primary_config">Primary configuration</string>
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user