Loading src/com/android/settings/slices/SettingsSliceProvider.java +56 −75 Original line number Diff line number Diff line Loading @@ -18,41 +18,39 @@ package com.android.settings.slices; import static android.Manifest.permission.READ_SEARCH_INDEXABLES; import static com.android.settings.wifi.calling.WifiCallingSliceHelper.PATH_WIFI_CALLING; import android.app.PendingIntent; import android.app.slice.SliceManager; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.graphics.drawable.Icon; import android.content.IntentFilter; import android.content.Context; import android.net.Uri; import android.net.wifi.WifiManager; import android.provider.Settings; import android.provider.SettingsSlicesContract; import android.support.annotation.VisibleForTesting; import android.support.v4.graphics.drawable.IconCompat; import android.text.TextUtils; import android.util.ArraySet; import android.util.Log; import android.util.Pair; import androidx.slice.Slice; import androidx.slice.SliceProvider; import androidx.slice.builders.ListBuilder; import androidx.slice.builders.SliceAction; import com.android.settings.R; import com.android.settings.overlay.FeatureFactory; import com.android.settings.wifi.WifiSliceBuilder; import com.android.settings.wifi.calling.WifiCallingSliceHelper; import com.android.settingslib.SliceBroadcastRelay; import com.android.settingslib.utils.ThreadUtils; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; import java.util.WeakHashMap; import java.util.concurrent.ConcurrentHashMap; import androidx.slice.Slice; import androidx.slice.SliceProvider; /** * A {@link SliceProvider} for Settings to enabled inline results in system apps. * Loading Loading @@ -84,10 +82,6 @@ public class SettingsSliceProvider extends SliceProvider { */ public static final String SLICE_AUTHORITY = "com.android.settings.slices"; public static final String PATH_WIFI = "wifi"; public static final String ACTION_WIFI_CHANGED = "com.android.settings.slice.action.WIFI_CHANGED"; /** * Action passed for changes to Toggle Slices. */ Loading Loading @@ -121,6 +115,8 @@ public class SettingsSliceProvider extends SliceProvider { @VisibleForTesting Map<Uri, SliceData> mSliceDataCache; final Set<Uri> mRegisteredUris = new ArraySet<>(); public SettingsSliceProvider() { super(READ_SEARCH_INDEXABLES); } Loading @@ -146,28 +142,37 @@ public class SettingsSliceProvider extends SliceProvider { @Override public void onSlicePinned(Uri sliceUri) { if (WifiSliceBuilder.WIFI_URI.equals(sliceUri)) { registerIntentToUri(WifiSliceBuilder.INTENT_FILTER , sliceUri); // TODO (b/) Register IntentFilters for database entries. mRegisteredUris.add(sliceUri); return; } // Start warming the slice, we expect someone will want it soon. loadSliceInBackground(sliceUri); } @Override public void onSliceUnpinned(Uri sliceUri) { if (mRegisteredUris.contains(sliceUri)) { SliceBroadcastRelay.unregisterReceivers(getContext(), sliceUri); mRegisteredUris.remove(sliceUri); } mSliceDataCache.remove(sliceUri); } @Override public Slice onBindSlice(Uri sliceUri) { String path = sliceUri.getPath(); // If adding a new Slice, do not directly match Slice URIs. // Use {@link SlicesDatabaseAccessor}. switch (path) { case "/" + PATH_WIFI: return createWifiSlice(sliceUri); case "/" + PATH_WIFI_CALLING: if (WifiCallingSliceHelper.WIFI_CALLING_URI.equals(sliceUri)) { return FeatureFactory.getFactory(getContext()) .getSlicesFeatureProvider() .getNewWifiCallingSliceHelper(getContext()) .createWifiCallingSlice(sliceUri); } else if (WifiSliceBuilder.WIFI_URI.equals(sliceUri)) { return WifiSliceBuilder.getSlice(getContext()); } SliceData cachedSliceData = mSliceWeakDataCache.get(sliceUri); Loading Loading @@ -223,11 +228,12 @@ public class SettingsSliceProvider extends SliceProvider { true /* isPlatformSlice */); final List<String> oemKeys = mSlicesDatabaseAccessor.getSliceKeys( false /* isPlatformSlice */); final List<Uri> allUris = buildUrisFromKeys(platformKeys, SettingsSlicesContract.AUTHORITY); allUris.addAll(buildUrisFromKeys(oemKeys, SettingsSliceProvider.SLICE_AUTHORITY)); descendants.addAll(buildUrisFromKeys(platformKeys, SettingsSlicesContract.AUTHORITY)); descendants.addAll(buildUrisFromKeys(oemKeys, SettingsSliceProvider.SLICE_AUTHORITY)); descendants.addAll(getSpecialCaseUris(true /* isPlatformSlice */)); descendants.addAll(getSpecialCaseUris(false /* isPlatformSlice */)); return allUris; return descendants; } // Path is anything but empty, "action", or "intent". Return empty list. Loading @@ -242,7 +248,9 @@ public class SettingsSliceProvider extends SliceProvider { // Can assume authority belongs to the provider. Return all Uris for the authority. final boolean isPlatformUri = TextUtils.equals(authority, SettingsSlicesContract.AUTHORITY); final List<String> keys = mSlicesDatabaseAccessor.getSliceKeys(isPlatformUri); return buildUrisFromKeys(keys, authority); descendants.addAll(buildUrisFromKeys(keys, authority)); descendants.addAll(getSpecialCaseUris(isPlatformUri)); return descendants; } private List<Uri> buildUrisFromKeys(List<String> keys, String authority) { Loading Loading @@ -295,55 +303,28 @@ public class SettingsSliceProvider extends SliceProvider { return new Slice.Builder(uri).build(); } // TODO (b/70622039) remove this when the proper wifi slice is enabled. private Slice createWifiSlice(Uri sliceUri) { // Get wifi state WifiManager wifiManager = (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE); int wifiState = wifiManager.getWifiState(); boolean wifiEnabled = false; String state; switch (wifiState) { case WifiManager.WIFI_STATE_DISABLED: case WifiManager.WIFI_STATE_DISABLING: state = getContext().getString(R.string.disconnected); break; case WifiManager.WIFI_STATE_ENABLED: case WifiManager.WIFI_STATE_ENABLING: state = wifiManager.getConnectionInfo().getSSID(); wifiEnabled = true; break; case WifiManager.WIFI_STATE_UNKNOWN: default: state = ""; // just don't show anything? break; private List<Uri> getSpecialCaseUris(boolean isPlatformUri) { if (isPlatformUri) { return getSpecialCasePlatformUris(); } return getSpecialCaseOemUris(); } boolean finalWifiEnabled = wifiEnabled; return new ListBuilder(getContext(), sliceUri) .setColor(R.color.material_blue_500) .addRow(b -> b .setTitle(getContext().getString(R.string.wifi_settings)) .setTitleItem(Icon.createWithResource(getContext(), R.drawable.wifi_signal)) .setSubtitle(state) .addEndItem(new SliceAction(getBroadcastIntent(ACTION_WIFI_CHANGED), null, finalWifiEnabled)) .setPrimaryAction( new SliceAction(getIntent(Settings.ACTION_WIFI_SETTINGS), (IconCompat) null, null))) .build(); private List<Uri> getSpecialCasePlatformUris() { return Arrays.asList(WifiSliceBuilder.WIFI_URI); } private PendingIntent getIntent(String action) { Intent intent = new Intent(action); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); PendingIntent pi = PendingIntent.getActivity(getContext(), 0, intent, 0); return pi; private List<Uri> getSpecialCaseOemUris() { return new ArrayList<>(); } private PendingIntent getBroadcastIntent(String action) { Intent intent = new Intent(action); intent.setClass(getContext(), SliceBroadcastReceiver.class); return PendingIntent.getBroadcast(getContext(), 0, intent, PendingIntent.FLAG_CANCEL_CURRENT); @VisibleForTesting /** * Registers an IntentFilter in SysUI to notify changes to {@param sliceUri} when broadcasts to * {@param intentFilter} happen. */ void registerIntentToUri(IntentFilter intentFilter, Uri sliceUri) { SliceBroadcastRelay.registerReceiver(getContext(), sliceUri, SliceBroadcastReceiver.class, intentFilter); } } src/com/android/settings/slices/SliceBroadcastReceiver.java +14 −18 Original line number Diff line number Diff line Loading @@ -18,18 +18,16 @@ package com.android.settings.slices; import static com.android.settings.slices.SettingsSliceProvider.ACTION_SLIDER_CHANGED; import static com.android.settings.slices.SettingsSliceProvider.ACTION_TOGGLE_CHANGED; import static com.android.settings.slices.SettingsSliceProvider.ACTION_WIFI_CHANGED; import static com.android.settings.slices.SettingsSliceProvider.EXTRA_SLICE_KEY; import static com.android.settings.slices.SettingsSliceProvider.EXTRA_SLICE_PLATFORM_DEFINED; import static com.android.settings.wifi.calling.WifiCallingSliceHelper.ACTION_WIFI_CALLING_CHANGED; import static com.android.settings.wifi.WifiSliceBuilder.ACTION_WIFI_SLICE_CHANGED; import android.app.slice.Slice; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.net.Uri; import android.net.wifi.WifiManager; import android.os.Handler; import android.provider.SettingsSlicesContract; import android.text.TextUtils; import android.util.Log; Loading @@ -40,6 +38,8 @@ import com.android.settings.core.BasePreferenceController; import com.android.settings.core.SliderPreferenceController; import com.android.settings.core.TogglePreferenceController; import com.android.settings.overlay.FeatureFactory; import com.android.settings.wifi.WifiSliceBuilder; import com.android.settingslib.SliceBroadcastRelay; /** * Responds to actions performed on slices and notifies slices of updates in state changes. Loading Loading @@ -67,18 +67,8 @@ public class SliceBroadcastReceiver extends BroadcastReceiver { final int newPosition = intent.getIntExtra(Slice.EXTRA_RANGE_VALUE, -1); handleSliderAction(context, key, newPosition, isPlatformSlice); break; case ACTION_WIFI_CHANGED: WifiManager wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); boolean newState = intent.getBooleanExtra(Slice.EXTRA_TOGGLE_STATE, wm.isWifiEnabled()); wm.setWifiEnabled(newState); // Wait a bit for wifi to update (TODO: is there a better way to do this?) Handler h = new Handler(); h.postDelayed(() -> { Uri uri = SliceBuilderUtils.getUri(SettingsSliceProvider.PATH_WIFI, false /* isPlatformSlice */); context.getContentResolver().notifyChange(uri, null); }, 1000); case ACTION_WIFI_SLICE_CHANGED: WifiSliceBuilder.handleUriChange(context, intent); break; case ACTION_WIFI_CALLING_CHANGED: FeatureFactory.getFactory(context) Loading @@ -86,6 +76,12 @@ public class SliceBroadcastReceiver extends BroadcastReceiver { .getNewWifiCallingSliceHelper(context) .handleWifiCallingChanged(intent); break; default: final String uriString = intent.getStringExtra(SliceBroadcastRelay.EXTRA_URI); if (!TextUtils.isEmpty(uriString)) { final Uri uri = Uri.parse(uriString); context.getContentResolver().notifyChange(uri, null /* observer */); } } } Loading src/com/android/settings/slices/SliceBuilderUtils.java +6 −2 Original line number Diff line number Diff line Loading @@ -39,7 +39,6 @@ import android.util.Pair; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.settings.R; import com.android.settings.SettingsActivity; import com.android.settings.SubSettings; import com.android.settings.Utils; import com.android.settings.core.BasePreferenceController; Loading @@ -47,6 +46,7 @@ import com.android.settings.core.SliderPreferenceController; import com.android.settings.core.TogglePreferenceController; import com.android.settings.overlay.FeatureFactory; import com.android.settings.search.DatabaseIndexingUtils; import com.android.settingslib.SliceBroadcastRelay; import com.android.settingslib.core.AbstractPreferenceController; import android.support.v4.graphics.drawable.IconCompat; Loading @@ -54,6 +54,7 @@ import android.support.v4.graphics.drawable.IconCompat; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; import androidx.slice.Slice; import androidx.slice.builders.ListBuilder; Loading Loading @@ -345,7 +346,10 @@ public class SliceBuilderUtils { final String keywordString = data.getKeywords(); if (keywordString != null) { final String[] keywordArray = keywordString.split(","); keywords.addAll(Arrays.asList(keywordArray)); final List<String> strippedKeywords = Arrays.stream(keywordArray) .map(s -> s = s.trim()) .collect(Collectors.toList()); keywords.addAll(strippedKeywords); } return keywords; Loading src/com/android/settings/wifi/WifiSliceBuilder.java 0 → 100644 +178 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source 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.settings.wifi; import static android.provider.SettingsSlicesContract.KEY_WIFI; import android.annotation.ColorInt; import android.app.PendingIntent; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.net.Uri; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.net.wifi.WifiSsid; import android.provider.SettingsSlicesContract; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.settings.R; import com.android.settings.SubSettings; import com.android.settings.Utils; import com.android.settings.search.DatabaseIndexingUtils; import com.android.settings.slices.SliceBroadcastReceiver; import com.android.settings.slices.SliceBuilderUtils; import androidx.slice.Slice; import androidx.slice.builders.ListBuilder; import androidx.slice.builders.SliceAction; import android.support.v4.graphics.drawable.IconCompat; import android.text.TextUtils; /** * Utility class to build a Wifi Slice, and handle all associated actions. */ public class WifiSliceBuilder { /** * Backing Uri for the Wifi Slice. */ public static final Uri WIFI_URI = new Uri.Builder() .scheme(ContentResolver.SCHEME_CONTENT) .authority(SettingsSlicesContract.AUTHORITY) .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION) .appendPath(KEY_WIFI) .build(); /** * Action notifying a change on the Wifi Slice. */ public static final String ACTION_WIFI_SLICE_CHANGED = "com.android.settings.wifi.action.WIFI_CHANGED"; public static final IntentFilter INTENT_FILTER = new IntentFilter(); static { INTENT_FILTER.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); INTENT_FILTER.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); } private WifiSliceBuilder() { } /** * Return a Wifi Slice bound to {@link #WIFI_URI}. * <p> * Note that you should register a listener with {@link #registerIntentFilter(Context, Uri)} * to get changes from Wifi. */ public static Slice getSlice(Context context) { final boolean isWifiEnabled = isWifiEnabled(context); final IconCompat icon = IconCompat.createWithResource(context, R.drawable.ic_settings_wireless); final String title = context.getString(R.string.wifi_settings); final CharSequence summary = getSummary(context); @ColorInt final int color = Utils.getColorAccent(context); final PendingIntent toggleAction = getBroadcastIntent(context); final PendingIntent primaryAction = getPrimaryAction(context); final SliceAction primarySliceAction = new SliceAction(primaryAction, icon, title); final SliceAction toggleSliceAction = new SliceAction(toggleAction, null /* actionTitle */, isWifiEnabled); return new ListBuilder(context, WIFI_URI, ListBuilder.INFINITY) .setAccentColor(color) .addRow(b -> b .setTitle(title) .setSubtitle(summary) .addEndItem(toggleSliceAction) .setPrimaryAction(primarySliceAction)) .build(); } /** * Update the current wifi status to the boolean value keyed by * {@link android.app.slice.Slice#EXTRA_TOGGLE_STATE} on {@param intent}. */ public static void handleUriChange(Context context, Intent intent) { final WifiManager wifiManager = context.getSystemService(WifiManager.class); final boolean newState = intent.getBooleanExtra(android.app.slice.Slice.EXTRA_TOGGLE_STATE, wifiManager.isWifiEnabled()); wifiManager.setWifiEnabled(newState); // Do not notifyChange on Uri. The service takes longer to update the current value than it // does for the Slice to check the current value again. Let {@link SliceBroadcastRelay} // handle it. } private static boolean isWifiEnabled(Context context) { final WifiManager wifiManager = context.getSystemService(WifiManager.class); switch (wifiManager.getWifiState()) { case WifiManager.WIFI_STATE_ENABLED: case WifiManager.WIFI_STATE_ENABLING: return true; case WifiManager.WIFI_STATE_DISABLED: case WifiManager.WIFI_STATE_DISABLING: case WifiManager.WIFI_STATE_UNKNOWN: default: return false; } } private static CharSequence getSummary(Context context) { final WifiManager wifiManager = context.getSystemService(WifiManager.class); switch (wifiManager.getWifiState()) { case WifiManager.WIFI_STATE_ENABLED: final String ssid = WifiInfo.removeDoubleQuotes(wifiManager.getConnectionInfo() .getSSID()); if (TextUtils.equals(ssid, WifiSsid.NONE)) { return context.getText(R.string.disconnected); } return ssid; case WifiManager.WIFI_STATE_ENABLING: return context.getText(R.string.disconnected); case WifiManager.WIFI_STATE_DISABLED: case WifiManager.WIFI_STATE_DISABLING: return context.getText(R.string.switch_off_text); case WifiManager.WIFI_STATE_UNKNOWN: default: return ""; } } private static PendingIntent getPrimaryAction(Context context) { final String screenTitle = context.getText(R.string.wifi_settings).toString(); final Uri contentUri = new Uri.Builder().appendPath(KEY_WIFI).build(); final Intent intent = DatabaseIndexingUtils.buildSearchResultPageIntent(context, WifiSettings.class.getName(), KEY_WIFI, screenTitle, MetricsEvent.DIALOG_WIFI_AP_EDIT); intent.setClassName(context.getPackageName(), SubSettings.class.getName()); intent.setData(contentUri); return PendingIntent.getActivity(context, 0 /* requestCode */, intent, 0 /* flags */); } private static PendingIntent getBroadcastIntent(Context context) { final Intent intent = new Intent(ACTION_WIFI_SLICE_CHANGED); intent.setClass(context, SliceBroadcastReceiver.class); return PendingIntent.getBroadcast(context, 0 /* requestCode */, intent, PendingIntent.FLAG_CANCEL_CURRENT); } } src/com/android/settings/wifi/calling/WifiCallingSliceHelper.java +12 −6 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import static android.app.slice.Slice.EXTRA_TOGGLE_STATE; import android.app.PendingIntent; import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.net.Uri; Loading @@ -38,6 +39,7 @@ import androidx.slice.builders.SliceAction; import com.android.ims.ImsManager; import com.android.internal.annotations.VisibleForTesting; import com.android.settings.R; import com.android.settings.slices.SettingsSliceProvider; import com.android.settings.slices.SliceBroadcastReceiver; import com.android.settings.slices.SliceBuilderUtils; Loading Loading @@ -77,14 +79,18 @@ public class WifiCallingSliceHelper { "android.settings.WIFI_CALLING_SETTINGS"; /** * Timeout for querying wifi calling setting from ims manager. * Full {@link Uri} for the Wifi Calling Slice. */ private static final int TIMEOUT_MILLIS = 2000; public static final Uri WIFI_CALLING_URI = new Uri.Builder() .scheme(ContentResolver.SCHEME_CONTENT) .authority(SettingsSliceProvider.SLICE_AUTHORITY) .appendPath(PATH_WIFI_CALLING) .build(); /** * Time for which data contained in the slice can remain fresh. * Timeout for querying wifi calling setting from ims manager. */ private static final int SLICE_TTL_MILLIS = 60000; private static final int TIMEOUT_MILLIS = 2000; protected SubscriptionManager mSubscriptionManager; private final Context mContext; Loading Loading @@ -182,7 +188,7 @@ public class WifiCallingSliceHelper { final IconCompat icon = IconCompat.createWithResource(mContext, R.drawable.wifi_signal); final String title = mContext.getString(R.string.wifi_calling_settings_title); return new ListBuilder(mContext, sliceUri, SLICE_TTL_MILLIS) return new ListBuilder(mContext, sliceUri, ListBuilder.INFINITY) .setColor(R.color.material_blue_500) .addRow(b -> b .setTitle(title) Loading Loading @@ -260,7 +266,7 @@ public class WifiCallingSliceHelper { private Slice getNonActionableWifiCallingSlice(String title, String subtitle, Uri sliceUri, PendingIntent primaryActionIntent) { final IconCompat icon = IconCompat.createWithResource(mContext, R.drawable.wifi_signal); return new ListBuilder(mContext, sliceUri, SLICE_TTL_MILLIS) return new ListBuilder(mContext, sliceUri, ListBuilder.INFINITY) .setColor(R.color.material_blue_500) .addRow(b -> b .setTitle(title) Loading Loading
src/com/android/settings/slices/SettingsSliceProvider.java +56 −75 Original line number Diff line number Diff line Loading @@ -18,41 +18,39 @@ package com.android.settings.slices; import static android.Manifest.permission.READ_SEARCH_INDEXABLES; import static com.android.settings.wifi.calling.WifiCallingSliceHelper.PATH_WIFI_CALLING; import android.app.PendingIntent; import android.app.slice.SliceManager; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.graphics.drawable.Icon; import android.content.IntentFilter; import android.content.Context; import android.net.Uri; import android.net.wifi.WifiManager; import android.provider.Settings; import android.provider.SettingsSlicesContract; import android.support.annotation.VisibleForTesting; import android.support.v4.graphics.drawable.IconCompat; import android.text.TextUtils; import android.util.ArraySet; import android.util.Log; import android.util.Pair; import androidx.slice.Slice; import androidx.slice.SliceProvider; import androidx.slice.builders.ListBuilder; import androidx.slice.builders.SliceAction; import com.android.settings.R; import com.android.settings.overlay.FeatureFactory; import com.android.settings.wifi.WifiSliceBuilder; import com.android.settings.wifi.calling.WifiCallingSliceHelper; import com.android.settingslib.SliceBroadcastRelay; import com.android.settingslib.utils.ThreadUtils; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; import java.util.WeakHashMap; import java.util.concurrent.ConcurrentHashMap; import androidx.slice.Slice; import androidx.slice.SliceProvider; /** * A {@link SliceProvider} for Settings to enabled inline results in system apps. * Loading Loading @@ -84,10 +82,6 @@ public class SettingsSliceProvider extends SliceProvider { */ public static final String SLICE_AUTHORITY = "com.android.settings.slices"; public static final String PATH_WIFI = "wifi"; public static final String ACTION_WIFI_CHANGED = "com.android.settings.slice.action.WIFI_CHANGED"; /** * Action passed for changes to Toggle Slices. */ Loading Loading @@ -121,6 +115,8 @@ public class SettingsSliceProvider extends SliceProvider { @VisibleForTesting Map<Uri, SliceData> mSliceDataCache; final Set<Uri> mRegisteredUris = new ArraySet<>(); public SettingsSliceProvider() { super(READ_SEARCH_INDEXABLES); } Loading @@ -146,28 +142,37 @@ public class SettingsSliceProvider extends SliceProvider { @Override public void onSlicePinned(Uri sliceUri) { if (WifiSliceBuilder.WIFI_URI.equals(sliceUri)) { registerIntentToUri(WifiSliceBuilder.INTENT_FILTER , sliceUri); // TODO (b/) Register IntentFilters for database entries. mRegisteredUris.add(sliceUri); return; } // Start warming the slice, we expect someone will want it soon. loadSliceInBackground(sliceUri); } @Override public void onSliceUnpinned(Uri sliceUri) { if (mRegisteredUris.contains(sliceUri)) { SliceBroadcastRelay.unregisterReceivers(getContext(), sliceUri); mRegisteredUris.remove(sliceUri); } mSliceDataCache.remove(sliceUri); } @Override public Slice onBindSlice(Uri sliceUri) { String path = sliceUri.getPath(); // If adding a new Slice, do not directly match Slice URIs. // Use {@link SlicesDatabaseAccessor}. switch (path) { case "/" + PATH_WIFI: return createWifiSlice(sliceUri); case "/" + PATH_WIFI_CALLING: if (WifiCallingSliceHelper.WIFI_CALLING_URI.equals(sliceUri)) { return FeatureFactory.getFactory(getContext()) .getSlicesFeatureProvider() .getNewWifiCallingSliceHelper(getContext()) .createWifiCallingSlice(sliceUri); } else if (WifiSliceBuilder.WIFI_URI.equals(sliceUri)) { return WifiSliceBuilder.getSlice(getContext()); } SliceData cachedSliceData = mSliceWeakDataCache.get(sliceUri); Loading Loading @@ -223,11 +228,12 @@ public class SettingsSliceProvider extends SliceProvider { true /* isPlatformSlice */); final List<String> oemKeys = mSlicesDatabaseAccessor.getSliceKeys( false /* isPlatformSlice */); final List<Uri> allUris = buildUrisFromKeys(platformKeys, SettingsSlicesContract.AUTHORITY); allUris.addAll(buildUrisFromKeys(oemKeys, SettingsSliceProvider.SLICE_AUTHORITY)); descendants.addAll(buildUrisFromKeys(platformKeys, SettingsSlicesContract.AUTHORITY)); descendants.addAll(buildUrisFromKeys(oemKeys, SettingsSliceProvider.SLICE_AUTHORITY)); descendants.addAll(getSpecialCaseUris(true /* isPlatformSlice */)); descendants.addAll(getSpecialCaseUris(false /* isPlatformSlice */)); return allUris; return descendants; } // Path is anything but empty, "action", or "intent". Return empty list. Loading @@ -242,7 +248,9 @@ public class SettingsSliceProvider extends SliceProvider { // Can assume authority belongs to the provider. Return all Uris for the authority. final boolean isPlatformUri = TextUtils.equals(authority, SettingsSlicesContract.AUTHORITY); final List<String> keys = mSlicesDatabaseAccessor.getSliceKeys(isPlatformUri); return buildUrisFromKeys(keys, authority); descendants.addAll(buildUrisFromKeys(keys, authority)); descendants.addAll(getSpecialCaseUris(isPlatformUri)); return descendants; } private List<Uri> buildUrisFromKeys(List<String> keys, String authority) { Loading Loading @@ -295,55 +303,28 @@ public class SettingsSliceProvider extends SliceProvider { return new Slice.Builder(uri).build(); } // TODO (b/70622039) remove this when the proper wifi slice is enabled. private Slice createWifiSlice(Uri sliceUri) { // Get wifi state WifiManager wifiManager = (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE); int wifiState = wifiManager.getWifiState(); boolean wifiEnabled = false; String state; switch (wifiState) { case WifiManager.WIFI_STATE_DISABLED: case WifiManager.WIFI_STATE_DISABLING: state = getContext().getString(R.string.disconnected); break; case WifiManager.WIFI_STATE_ENABLED: case WifiManager.WIFI_STATE_ENABLING: state = wifiManager.getConnectionInfo().getSSID(); wifiEnabled = true; break; case WifiManager.WIFI_STATE_UNKNOWN: default: state = ""; // just don't show anything? break; private List<Uri> getSpecialCaseUris(boolean isPlatformUri) { if (isPlatformUri) { return getSpecialCasePlatformUris(); } return getSpecialCaseOemUris(); } boolean finalWifiEnabled = wifiEnabled; return new ListBuilder(getContext(), sliceUri) .setColor(R.color.material_blue_500) .addRow(b -> b .setTitle(getContext().getString(R.string.wifi_settings)) .setTitleItem(Icon.createWithResource(getContext(), R.drawable.wifi_signal)) .setSubtitle(state) .addEndItem(new SliceAction(getBroadcastIntent(ACTION_WIFI_CHANGED), null, finalWifiEnabled)) .setPrimaryAction( new SliceAction(getIntent(Settings.ACTION_WIFI_SETTINGS), (IconCompat) null, null))) .build(); private List<Uri> getSpecialCasePlatformUris() { return Arrays.asList(WifiSliceBuilder.WIFI_URI); } private PendingIntent getIntent(String action) { Intent intent = new Intent(action); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); PendingIntent pi = PendingIntent.getActivity(getContext(), 0, intent, 0); return pi; private List<Uri> getSpecialCaseOemUris() { return new ArrayList<>(); } private PendingIntent getBroadcastIntent(String action) { Intent intent = new Intent(action); intent.setClass(getContext(), SliceBroadcastReceiver.class); return PendingIntent.getBroadcast(getContext(), 0, intent, PendingIntent.FLAG_CANCEL_CURRENT); @VisibleForTesting /** * Registers an IntentFilter in SysUI to notify changes to {@param sliceUri} when broadcasts to * {@param intentFilter} happen. */ void registerIntentToUri(IntentFilter intentFilter, Uri sliceUri) { SliceBroadcastRelay.registerReceiver(getContext(), sliceUri, SliceBroadcastReceiver.class, intentFilter); } }
src/com/android/settings/slices/SliceBroadcastReceiver.java +14 −18 Original line number Diff line number Diff line Loading @@ -18,18 +18,16 @@ package com.android.settings.slices; import static com.android.settings.slices.SettingsSliceProvider.ACTION_SLIDER_CHANGED; import static com.android.settings.slices.SettingsSliceProvider.ACTION_TOGGLE_CHANGED; import static com.android.settings.slices.SettingsSliceProvider.ACTION_WIFI_CHANGED; import static com.android.settings.slices.SettingsSliceProvider.EXTRA_SLICE_KEY; import static com.android.settings.slices.SettingsSliceProvider.EXTRA_SLICE_PLATFORM_DEFINED; import static com.android.settings.wifi.calling.WifiCallingSliceHelper.ACTION_WIFI_CALLING_CHANGED; import static com.android.settings.wifi.WifiSliceBuilder.ACTION_WIFI_SLICE_CHANGED; import android.app.slice.Slice; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.net.Uri; import android.net.wifi.WifiManager; import android.os.Handler; import android.provider.SettingsSlicesContract; import android.text.TextUtils; import android.util.Log; Loading @@ -40,6 +38,8 @@ import com.android.settings.core.BasePreferenceController; import com.android.settings.core.SliderPreferenceController; import com.android.settings.core.TogglePreferenceController; import com.android.settings.overlay.FeatureFactory; import com.android.settings.wifi.WifiSliceBuilder; import com.android.settingslib.SliceBroadcastRelay; /** * Responds to actions performed on slices and notifies slices of updates in state changes. Loading Loading @@ -67,18 +67,8 @@ public class SliceBroadcastReceiver extends BroadcastReceiver { final int newPosition = intent.getIntExtra(Slice.EXTRA_RANGE_VALUE, -1); handleSliderAction(context, key, newPosition, isPlatformSlice); break; case ACTION_WIFI_CHANGED: WifiManager wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); boolean newState = intent.getBooleanExtra(Slice.EXTRA_TOGGLE_STATE, wm.isWifiEnabled()); wm.setWifiEnabled(newState); // Wait a bit for wifi to update (TODO: is there a better way to do this?) Handler h = new Handler(); h.postDelayed(() -> { Uri uri = SliceBuilderUtils.getUri(SettingsSliceProvider.PATH_WIFI, false /* isPlatformSlice */); context.getContentResolver().notifyChange(uri, null); }, 1000); case ACTION_WIFI_SLICE_CHANGED: WifiSliceBuilder.handleUriChange(context, intent); break; case ACTION_WIFI_CALLING_CHANGED: FeatureFactory.getFactory(context) Loading @@ -86,6 +76,12 @@ public class SliceBroadcastReceiver extends BroadcastReceiver { .getNewWifiCallingSliceHelper(context) .handleWifiCallingChanged(intent); break; default: final String uriString = intent.getStringExtra(SliceBroadcastRelay.EXTRA_URI); if (!TextUtils.isEmpty(uriString)) { final Uri uri = Uri.parse(uriString); context.getContentResolver().notifyChange(uri, null /* observer */); } } } Loading
src/com/android/settings/slices/SliceBuilderUtils.java +6 −2 Original line number Diff line number Diff line Loading @@ -39,7 +39,6 @@ import android.util.Pair; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.settings.R; import com.android.settings.SettingsActivity; import com.android.settings.SubSettings; import com.android.settings.Utils; import com.android.settings.core.BasePreferenceController; Loading @@ -47,6 +46,7 @@ import com.android.settings.core.SliderPreferenceController; import com.android.settings.core.TogglePreferenceController; import com.android.settings.overlay.FeatureFactory; import com.android.settings.search.DatabaseIndexingUtils; import com.android.settingslib.SliceBroadcastRelay; import com.android.settingslib.core.AbstractPreferenceController; import android.support.v4.graphics.drawable.IconCompat; Loading @@ -54,6 +54,7 @@ import android.support.v4.graphics.drawable.IconCompat; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; import androidx.slice.Slice; import androidx.slice.builders.ListBuilder; Loading Loading @@ -345,7 +346,10 @@ public class SliceBuilderUtils { final String keywordString = data.getKeywords(); if (keywordString != null) { final String[] keywordArray = keywordString.split(","); keywords.addAll(Arrays.asList(keywordArray)); final List<String> strippedKeywords = Arrays.stream(keywordArray) .map(s -> s = s.trim()) .collect(Collectors.toList()); keywords.addAll(strippedKeywords); } return keywords; Loading
src/com/android/settings/wifi/WifiSliceBuilder.java 0 → 100644 +178 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source 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.settings.wifi; import static android.provider.SettingsSlicesContract.KEY_WIFI; import android.annotation.ColorInt; import android.app.PendingIntent; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.net.Uri; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.net.wifi.WifiSsid; import android.provider.SettingsSlicesContract; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.settings.R; import com.android.settings.SubSettings; import com.android.settings.Utils; import com.android.settings.search.DatabaseIndexingUtils; import com.android.settings.slices.SliceBroadcastReceiver; import com.android.settings.slices.SliceBuilderUtils; import androidx.slice.Slice; import androidx.slice.builders.ListBuilder; import androidx.slice.builders.SliceAction; import android.support.v4.graphics.drawable.IconCompat; import android.text.TextUtils; /** * Utility class to build a Wifi Slice, and handle all associated actions. */ public class WifiSliceBuilder { /** * Backing Uri for the Wifi Slice. */ public static final Uri WIFI_URI = new Uri.Builder() .scheme(ContentResolver.SCHEME_CONTENT) .authority(SettingsSlicesContract.AUTHORITY) .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION) .appendPath(KEY_WIFI) .build(); /** * Action notifying a change on the Wifi Slice. */ public static final String ACTION_WIFI_SLICE_CHANGED = "com.android.settings.wifi.action.WIFI_CHANGED"; public static final IntentFilter INTENT_FILTER = new IntentFilter(); static { INTENT_FILTER.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); INTENT_FILTER.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); } private WifiSliceBuilder() { } /** * Return a Wifi Slice bound to {@link #WIFI_URI}. * <p> * Note that you should register a listener with {@link #registerIntentFilter(Context, Uri)} * to get changes from Wifi. */ public static Slice getSlice(Context context) { final boolean isWifiEnabled = isWifiEnabled(context); final IconCompat icon = IconCompat.createWithResource(context, R.drawable.ic_settings_wireless); final String title = context.getString(R.string.wifi_settings); final CharSequence summary = getSummary(context); @ColorInt final int color = Utils.getColorAccent(context); final PendingIntent toggleAction = getBroadcastIntent(context); final PendingIntent primaryAction = getPrimaryAction(context); final SliceAction primarySliceAction = new SliceAction(primaryAction, icon, title); final SliceAction toggleSliceAction = new SliceAction(toggleAction, null /* actionTitle */, isWifiEnabled); return new ListBuilder(context, WIFI_URI, ListBuilder.INFINITY) .setAccentColor(color) .addRow(b -> b .setTitle(title) .setSubtitle(summary) .addEndItem(toggleSliceAction) .setPrimaryAction(primarySliceAction)) .build(); } /** * Update the current wifi status to the boolean value keyed by * {@link android.app.slice.Slice#EXTRA_TOGGLE_STATE} on {@param intent}. */ public static void handleUriChange(Context context, Intent intent) { final WifiManager wifiManager = context.getSystemService(WifiManager.class); final boolean newState = intent.getBooleanExtra(android.app.slice.Slice.EXTRA_TOGGLE_STATE, wifiManager.isWifiEnabled()); wifiManager.setWifiEnabled(newState); // Do not notifyChange on Uri. The service takes longer to update the current value than it // does for the Slice to check the current value again. Let {@link SliceBroadcastRelay} // handle it. } private static boolean isWifiEnabled(Context context) { final WifiManager wifiManager = context.getSystemService(WifiManager.class); switch (wifiManager.getWifiState()) { case WifiManager.WIFI_STATE_ENABLED: case WifiManager.WIFI_STATE_ENABLING: return true; case WifiManager.WIFI_STATE_DISABLED: case WifiManager.WIFI_STATE_DISABLING: case WifiManager.WIFI_STATE_UNKNOWN: default: return false; } } private static CharSequence getSummary(Context context) { final WifiManager wifiManager = context.getSystemService(WifiManager.class); switch (wifiManager.getWifiState()) { case WifiManager.WIFI_STATE_ENABLED: final String ssid = WifiInfo.removeDoubleQuotes(wifiManager.getConnectionInfo() .getSSID()); if (TextUtils.equals(ssid, WifiSsid.NONE)) { return context.getText(R.string.disconnected); } return ssid; case WifiManager.WIFI_STATE_ENABLING: return context.getText(R.string.disconnected); case WifiManager.WIFI_STATE_DISABLED: case WifiManager.WIFI_STATE_DISABLING: return context.getText(R.string.switch_off_text); case WifiManager.WIFI_STATE_UNKNOWN: default: return ""; } } private static PendingIntent getPrimaryAction(Context context) { final String screenTitle = context.getText(R.string.wifi_settings).toString(); final Uri contentUri = new Uri.Builder().appendPath(KEY_WIFI).build(); final Intent intent = DatabaseIndexingUtils.buildSearchResultPageIntent(context, WifiSettings.class.getName(), KEY_WIFI, screenTitle, MetricsEvent.DIALOG_WIFI_AP_EDIT); intent.setClassName(context.getPackageName(), SubSettings.class.getName()); intent.setData(contentUri); return PendingIntent.getActivity(context, 0 /* requestCode */, intent, 0 /* flags */); } private static PendingIntent getBroadcastIntent(Context context) { final Intent intent = new Intent(ACTION_WIFI_SLICE_CHANGED); intent.setClass(context, SliceBroadcastReceiver.class); return PendingIntent.getBroadcast(context, 0 /* requestCode */, intent, PendingIntent.FLAG_CANCEL_CURRENT); } }
src/com/android/settings/wifi/calling/WifiCallingSliceHelper.java +12 −6 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import static android.app.slice.Slice.EXTRA_TOGGLE_STATE; import android.app.PendingIntent; import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.net.Uri; Loading @@ -38,6 +39,7 @@ import androidx.slice.builders.SliceAction; import com.android.ims.ImsManager; import com.android.internal.annotations.VisibleForTesting; import com.android.settings.R; import com.android.settings.slices.SettingsSliceProvider; import com.android.settings.slices.SliceBroadcastReceiver; import com.android.settings.slices.SliceBuilderUtils; Loading Loading @@ -77,14 +79,18 @@ public class WifiCallingSliceHelper { "android.settings.WIFI_CALLING_SETTINGS"; /** * Timeout for querying wifi calling setting from ims manager. * Full {@link Uri} for the Wifi Calling Slice. */ private static final int TIMEOUT_MILLIS = 2000; public static final Uri WIFI_CALLING_URI = new Uri.Builder() .scheme(ContentResolver.SCHEME_CONTENT) .authority(SettingsSliceProvider.SLICE_AUTHORITY) .appendPath(PATH_WIFI_CALLING) .build(); /** * Time for which data contained in the slice can remain fresh. * Timeout for querying wifi calling setting from ims manager. */ private static final int SLICE_TTL_MILLIS = 60000; private static final int TIMEOUT_MILLIS = 2000; protected SubscriptionManager mSubscriptionManager; private final Context mContext; Loading Loading @@ -182,7 +188,7 @@ public class WifiCallingSliceHelper { final IconCompat icon = IconCompat.createWithResource(mContext, R.drawable.wifi_signal); final String title = mContext.getString(R.string.wifi_calling_settings_title); return new ListBuilder(mContext, sliceUri, SLICE_TTL_MILLIS) return new ListBuilder(mContext, sliceUri, ListBuilder.INFINITY) .setColor(R.color.material_blue_500) .addRow(b -> b .setTitle(title) Loading Loading @@ -260,7 +266,7 @@ public class WifiCallingSliceHelper { private Slice getNonActionableWifiCallingSlice(String title, String subtitle, Uri sliceUri, PendingIntent primaryActionIntent) { final IconCompat icon = IconCompat.createWithResource(mContext, R.drawable.wifi_signal); return new ListBuilder(mContext, sliceUri, SLICE_TTL_MILLIS) return new ListBuilder(mContext, sliceUri, ListBuilder.INFINITY) .setColor(R.color.material_blue_500) .addRow(b -> b .setTitle(title) Loading