Loading proguard.flags +6 −1 Original line number Diff line number Diff line Loading @@ -61,3 +61,8 @@ -keepclasseswithmembers class * implements com.android.settings.slices.CustomSliceable { public <init>(android.content.Context); } # Keep classes that extends SliceBackgroundWorker, which are used by reflection. -keepclasseswithmembers class * extends com.android.settings.slices.SliceBackgroundWorker { public <init>(android.content.Context, android.net.Uri); } src/com/android/settings/slices/CustomSliceable.java +4 −3 Original line number Diff line number Diff line Loading @@ -91,11 +91,12 @@ public interface CustomSliceable { /** * Settings Slices which can represent component lists that are updatable by the * {@link SliceBackgroundWorker} returned here. * {@link SliceBackgroundWorker} class returned here. * * @return a {@link SliceBackgroundWorker} for fetching the list of results in the background. * @return a {@link SliceBackgroundWorker} class for fetching the list of results in the * background. */ default SliceBackgroundWorker getBackgroundWorker() { default Class<? extends SliceBackgroundWorker> getBackgroundWorkerClass() { return null; } Loading src/com/android/settings/slices/SettingsSliceProvider.java +13 −23 Original line number Diff line number Diff line Loading @@ -52,7 +52,6 @@ import com.android.settings.wifi.calling.WifiCallingSliceHelper; import com.android.settingslib.SliceBroadcastRelay; import com.android.settingslib.utils.ThreadUtils; import java.io.IOException; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Arrays; Loading Loading @@ -134,8 +133,7 @@ public class SettingsSliceProvider extends SliceProvider { final Set<Uri> mRegisteredUris = new ArraySet<>(); final Map<Uri, SliceBackgroundWorker> mWorkerMap = new ArrayMap<>(); final Set<SliceBackgroundWorker> mLiveWorkers = new ArraySet<>(); final Map<Uri, SliceBackgroundWorker> mPinnedWorkers = new ArrayMap<>(); public SettingsSliceProvider() { super(READ_SEARCH_INDEXABLES); Loading Loading @@ -365,46 +363,38 @@ public class SettingsSliceProvider extends SliceProvider { } private void startBackgroundWorker(CustomSliceable sliceable) { final SliceBackgroundWorker worker = sliceable.getBackgroundWorker(); if (worker == null) { final Class workerClass = sliceable.getBackgroundWorkerClass(); if (workerClass == null) { return; } final Uri uri = sliceable.getUri(); if (mWorkerMap.containsKey(uri)) { if (mPinnedWorkers.containsKey(uri)) { return; } Log.d(TAG, "Starting background worker for: " + uri); mWorkerMap.put(uri, worker); if (!mLiveWorkers.contains(worker)) { mLiveWorkers.add(worker); } final SliceBackgroundWorker worker = SliceBackgroundWorker.getInstance( getContext(), sliceable); mPinnedWorkers.put(uri, worker); worker.onSlicePinned(); } private void stopBackgroundWorker(Uri uri) { final SliceBackgroundWorker worker = mWorkerMap.get(uri); final SliceBackgroundWorker worker = mPinnedWorkers.get(uri); if (worker != null) { Log.d(TAG, "Stopping background worker for: " + uri); worker.onSliceUnpinned(); mWorkerMap.remove(uri); mPinnedWorkers.remove(uri); } } @Override public void shutdown() { for (SliceBackgroundWorker worker : mLiveWorkers) { ThreadUtils.postOnMainThread(() -> { try { worker.close(); } catch (IOException e) { Log.w(TAG, "Exception when shutting down worker", e); } SliceBackgroundWorker.shutdown(); }); } mLiveWorkers.clear(); } private List<Uri> buildUrisFromKeys(List<String> keys, String authority) { final List<Uri> descendants = new ArrayList<>(); Loading src/com/android/settings/slices/SliceBackgroundWorker.java +58 −7 Original line number Diff line number Diff line Loading @@ -17,35 +17,86 @@ package com.android.settings.slices; import android.annotation.MainThread; import android.content.ContentResolver; import android.content.Context; import android.net.Uri; import android.util.ArrayMap; import android.util.Log; import java.io.Closeable; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.List; import java.util.Map; /** * The Slice background worker is used to make Settings Slices be able to work with data that is * changing continuously, e.g. available Wi-Fi networks. * * The background worker will be started at {@link SettingsSliceProvider#onSlicePinned(Uri)}, and be * stopped at {@link SettingsSliceProvider#onSliceUnpinned(Uri)}. * The background worker will be started at {@link SettingsSliceProvider#onSlicePinned(Uri)}, be * stopped at {@link SettingsSliceProvider#onSliceUnpinned(Uri)}, and be closed at {@link * SettingsSliceProvider#shutdown()}. * * {@link SliceBackgroundWorker} caches the results, uses the cache to compare if there is any data * changed, and then notifies the Slice {@link Uri} to update. * * It also stores all instances of all workers to ensure each worker is a Singleton. */ public abstract class SliceBackgroundWorker<E> implements Closeable { private final ContentResolver mContentResolver; private static final String TAG = "SliceBackgroundWorker"; private static final Map<Uri, SliceBackgroundWorker> LIVE_WORKERS = new ArrayMap<>(); private final Context mContext; private final Uri mUri; private List<E> mCachedResults; protected SliceBackgroundWorker(ContentResolver cr, Uri uri) { mContentResolver = cr; protected SliceBackgroundWorker(Context context, Uri uri) { mContext = context; mUri = uri; } /** * Returns the singleton instance of the {@link SliceBackgroundWorker} for specified {@link * CustomSliceable} */ public static SliceBackgroundWorker getInstance(Context context, CustomSliceable sliceable) { final Uri uri = sliceable.getUri(); final Class<? extends SliceBackgroundWorker> workerClass = sliceable.getBackgroundWorkerClass(); SliceBackgroundWorker worker = LIVE_WORKERS.get(uri); if (worker == null) { worker = createInstance(context, uri, workerClass); LIVE_WORKERS.put(uri, worker); } return worker; } private static SliceBackgroundWorker createInstance(Context context, Uri uri, Class<? extends SliceBackgroundWorker> clazz) { Log.d(TAG, "create instance: " + clazz); try { return clazz.getConstructor(Context.class, Uri.class).newInstance(context, uri); } catch (NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) { throw new IllegalStateException( "Invalid slice background worker: " + clazz, e); } } static void shutdown() { for (SliceBackgroundWorker worker : LIVE_WORKERS.values()) { try { worker.close(); } catch (IOException e) { Log.w(TAG, "Shutting down worker failed", e); } } LIVE_WORKERS.clear(); } /** * Called when the Slice is pinned. This is the place to register callbacks or initialize scan * tasks. Loading Loading @@ -83,7 +134,7 @@ public abstract class SliceBackgroundWorker<E> implements Closeable { if (needNotify) { mCachedResults = results; mContentResolver.notifyChange(mUri, null); mContext.getContentResolver().notifyChange(mUri, null); } } } src/com/android/settings/wifi/WifiSlice.java +8 −18 Original line number Diff line number Diff line Loading @@ -121,7 +121,7 @@ public class WifiSlice implements CustomSliceable { return listBuilder.build(); } List<AccessPoint> results = getBackgroundWorker().getResults(); List<AccessPoint> results = SliceBackgroundWorker.getInstance(mContext, this).getResults(); if (results == null) { results = new ArrayList<>(); } Loading Loading @@ -264,36 +264,27 @@ public class WifiSlice implements CustomSliceable { } @Override public SliceBackgroundWorker getBackgroundWorker() { return WifiScanWorker.getInstance(mContext, WIFI_URI); public Class getBackgroundWorkerClass() { return WifiScanWorker.class; } private static class WifiScanWorker extends SliceBackgroundWorker<AccessPoint> public static class WifiScanWorker extends SliceBackgroundWorker<AccessPoint> implements WifiTracker.WifiListener { // TODO: enforce all the SliceBackgroundWorkers being singletons at syntax level private static WifiScanWorker mWifiScanWorker; private final Context mContext; private WifiTracker mWifiTracker; private WifiScanWorker(Context context, Uri uri) { super(context.getContentResolver(), uri); public WifiScanWorker(Context context, Uri uri) { super(context, uri); mContext = context; } public static WifiScanWorker getInstance(Context context, Uri uri) { if (mWifiScanWorker == null) { mWifiScanWorker = new WifiScanWorker(context, uri); } return mWifiScanWorker; } @Override protected void onSlicePinned() { if (mWifiTracker == null) { mWifiTracker = new WifiTracker(mContext, this, true, true); mWifiTracker = new WifiTracker(mContext, this /* wifiListener */, true /* includeSaved */, true /* includeScans */); } mWifiTracker.onStart(); onAccessPointsChanged(); Loading @@ -307,7 +298,6 @@ public class WifiSlice implements CustomSliceable { @Override public void close() { mWifiTracker.onDestroy(); mWifiScanWorker = null; } @Override Loading Loading
proguard.flags +6 −1 Original line number Diff line number Diff line Loading @@ -61,3 +61,8 @@ -keepclasseswithmembers class * implements com.android.settings.slices.CustomSliceable { public <init>(android.content.Context); } # Keep classes that extends SliceBackgroundWorker, which are used by reflection. -keepclasseswithmembers class * extends com.android.settings.slices.SliceBackgroundWorker { public <init>(android.content.Context, android.net.Uri); }
src/com/android/settings/slices/CustomSliceable.java +4 −3 Original line number Diff line number Diff line Loading @@ -91,11 +91,12 @@ public interface CustomSliceable { /** * Settings Slices which can represent component lists that are updatable by the * {@link SliceBackgroundWorker} returned here. * {@link SliceBackgroundWorker} class returned here. * * @return a {@link SliceBackgroundWorker} for fetching the list of results in the background. * @return a {@link SliceBackgroundWorker} class for fetching the list of results in the * background. */ default SliceBackgroundWorker getBackgroundWorker() { default Class<? extends SliceBackgroundWorker> getBackgroundWorkerClass() { return null; } Loading
src/com/android/settings/slices/SettingsSliceProvider.java +13 −23 Original line number Diff line number Diff line Loading @@ -52,7 +52,6 @@ import com.android.settings.wifi.calling.WifiCallingSliceHelper; import com.android.settingslib.SliceBroadcastRelay; import com.android.settingslib.utils.ThreadUtils; import java.io.IOException; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Arrays; Loading Loading @@ -134,8 +133,7 @@ public class SettingsSliceProvider extends SliceProvider { final Set<Uri> mRegisteredUris = new ArraySet<>(); final Map<Uri, SliceBackgroundWorker> mWorkerMap = new ArrayMap<>(); final Set<SliceBackgroundWorker> mLiveWorkers = new ArraySet<>(); final Map<Uri, SliceBackgroundWorker> mPinnedWorkers = new ArrayMap<>(); public SettingsSliceProvider() { super(READ_SEARCH_INDEXABLES); Loading Loading @@ -365,46 +363,38 @@ public class SettingsSliceProvider extends SliceProvider { } private void startBackgroundWorker(CustomSliceable sliceable) { final SliceBackgroundWorker worker = sliceable.getBackgroundWorker(); if (worker == null) { final Class workerClass = sliceable.getBackgroundWorkerClass(); if (workerClass == null) { return; } final Uri uri = sliceable.getUri(); if (mWorkerMap.containsKey(uri)) { if (mPinnedWorkers.containsKey(uri)) { return; } Log.d(TAG, "Starting background worker for: " + uri); mWorkerMap.put(uri, worker); if (!mLiveWorkers.contains(worker)) { mLiveWorkers.add(worker); } final SliceBackgroundWorker worker = SliceBackgroundWorker.getInstance( getContext(), sliceable); mPinnedWorkers.put(uri, worker); worker.onSlicePinned(); } private void stopBackgroundWorker(Uri uri) { final SliceBackgroundWorker worker = mWorkerMap.get(uri); final SliceBackgroundWorker worker = mPinnedWorkers.get(uri); if (worker != null) { Log.d(TAG, "Stopping background worker for: " + uri); worker.onSliceUnpinned(); mWorkerMap.remove(uri); mPinnedWorkers.remove(uri); } } @Override public void shutdown() { for (SliceBackgroundWorker worker : mLiveWorkers) { ThreadUtils.postOnMainThread(() -> { try { worker.close(); } catch (IOException e) { Log.w(TAG, "Exception when shutting down worker", e); } SliceBackgroundWorker.shutdown(); }); } mLiveWorkers.clear(); } private List<Uri> buildUrisFromKeys(List<String> keys, String authority) { final List<Uri> descendants = new ArrayList<>(); Loading
src/com/android/settings/slices/SliceBackgroundWorker.java +58 −7 Original line number Diff line number Diff line Loading @@ -17,35 +17,86 @@ package com.android.settings.slices; import android.annotation.MainThread; import android.content.ContentResolver; import android.content.Context; import android.net.Uri; import android.util.ArrayMap; import android.util.Log; import java.io.Closeable; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.List; import java.util.Map; /** * The Slice background worker is used to make Settings Slices be able to work with data that is * changing continuously, e.g. available Wi-Fi networks. * * The background worker will be started at {@link SettingsSliceProvider#onSlicePinned(Uri)}, and be * stopped at {@link SettingsSliceProvider#onSliceUnpinned(Uri)}. * The background worker will be started at {@link SettingsSliceProvider#onSlicePinned(Uri)}, be * stopped at {@link SettingsSliceProvider#onSliceUnpinned(Uri)}, and be closed at {@link * SettingsSliceProvider#shutdown()}. * * {@link SliceBackgroundWorker} caches the results, uses the cache to compare if there is any data * changed, and then notifies the Slice {@link Uri} to update. * * It also stores all instances of all workers to ensure each worker is a Singleton. */ public abstract class SliceBackgroundWorker<E> implements Closeable { private final ContentResolver mContentResolver; private static final String TAG = "SliceBackgroundWorker"; private static final Map<Uri, SliceBackgroundWorker> LIVE_WORKERS = new ArrayMap<>(); private final Context mContext; private final Uri mUri; private List<E> mCachedResults; protected SliceBackgroundWorker(ContentResolver cr, Uri uri) { mContentResolver = cr; protected SliceBackgroundWorker(Context context, Uri uri) { mContext = context; mUri = uri; } /** * Returns the singleton instance of the {@link SliceBackgroundWorker} for specified {@link * CustomSliceable} */ public static SliceBackgroundWorker getInstance(Context context, CustomSliceable sliceable) { final Uri uri = sliceable.getUri(); final Class<? extends SliceBackgroundWorker> workerClass = sliceable.getBackgroundWorkerClass(); SliceBackgroundWorker worker = LIVE_WORKERS.get(uri); if (worker == null) { worker = createInstance(context, uri, workerClass); LIVE_WORKERS.put(uri, worker); } return worker; } private static SliceBackgroundWorker createInstance(Context context, Uri uri, Class<? extends SliceBackgroundWorker> clazz) { Log.d(TAG, "create instance: " + clazz); try { return clazz.getConstructor(Context.class, Uri.class).newInstance(context, uri); } catch (NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) { throw new IllegalStateException( "Invalid slice background worker: " + clazz, e); } } static void shutdown() { for (SliceBackgroundWorker worker : LIVE_WORKERS.values()) { try { worker.close(); } catch (IOException e) { Log.w(TAG, "Shutting down worker failed", e); } } LIVE_WORKERS.clear(); } /** * Called when the Slice is pinned. This is the place to register callbacks or initialize scan * tasks. Loading Loading @@ -83,7 +134,7 @@ public abstract class SliceBackgroundWorker<E> implements Closeable { if (needNotify) { mCachedResults = results; mContentResolver.notifyChange(mUri, null); mContext.getContentResolver().notifyChange(mUri, null); } } }
src/com/android/settings/wifi/WifiSlice.java +8 −18 Original line number Diff line number Diff line Loading @@ -121,7 +121,7 @@ public class WifiSlice implements CustomSliceable { return listBuilder.build(); } List<AccessPoint> results = getBackgroundWorker().getResults(); List<AccessPoint> results = SliceBackgroundWorker.getInstance(mContext, this).getResults(); if (results == null) { results = new ArrayList<>(); } Loading Loading @@ -264,36 +264,27 @@ public class WifiSlice implements CustomSliceable { } @Override public SliceBackgroundWorker getBackgroundWorker() { return WifiScanWorker.getInstance(mContext, WIFI_URI); public Class getBackgroundWorkerClass() { return WifiScanWorker.class; } private static class WifiScanWorker extends SliceBackgroundWorker<AccessPoint> public static class WifiScanWorker extends SliceBackgroundWorker<AccessPoint> implements WifiTracker.WifiListener { // TODO: enforce all the SliceBackgroundWorkers being singletons at syntax level private static WifiScanWorker mWifiScanWorker; private final Context mContext; private WifiTracker mWifiTracker; private WifiScanWorker(Context context, Uri uri) { super(context.getContentResolver(), uri); public WifiScanWorker(Context context, Uri uri) { super(context, uri); mContext = context; } public static WifiScanWorker getInstance(Context context, Uri uri) { if (mWifiScanWorker == null) { mWifiScanWorker = new WifiScanWorker(context, uri); } return mWifiScanWorker; } @Override protected void onSlicePinned() { if (mWifiTracker == null) { mWifiTracker = new WifiTracker(mContext, this, true, true); mWifiTracker = new WifiTracker(mContext, this /* wifiListener */, true /* includeSaved */, true /* includeScans */); } mWifiTracker.onStart(); onAccessPointsChanged(); Loading @@ -307,7 +298,6 @@ public class WifiSlice implements CustomSliceable { @Override public void close() { mWifiTracker.onDestroy(); mWifiScanWorker = null; } @Override Loading