Migrate some suggestions related classes SettingsLib(II)

Remove classes from Settings.

Test: mm Settings/tests/robotests

Change-Id: I0f046d6a750bc53251deb44887e8665e6d545515
This commit is contained in:
Zhizhi Liu
2018-01-18 14:05:58 -08:00
parent b441d90f8c
commit caeb1720da
17 changed files with 15 additions and 560 deletions

View File

@@ -45,13 +45,13 @@ import com.android.settings.dashboard.DashboardData.SuggestionConditionHeaderDat
import com.android.settings.dashboard.conditional.Condition;
import com.android.settings.dashboard.conditional.ConditionAdapter;
import com.android.settings.dashboard.suggestions.SuggestionAdapter;
import com.android.settings.dashboard.suggestions.SuggestionControllerMixin;
import com.android.settings.dashboard.suggestions.SuggestionDismissController;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.Utils;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import com.android.settingslib.drawer.DashboardCategory;
import com.android.settingslib.drawer.Tile;
import com.android.settingslib.suggestions.SuggestionControllerMixin;
import java.util.ArrayList;
import java.util.List;

View File

@@ -43,7 +43,6 @@ import com.android.settings.dashboard.DashboardDataV2.ConditionHeaderData;
import com.android.settings.dashboard.conditional.Condition;
import com.android.settings.dashboard.conditional.ConditionAdapterV2;
import com.android.settings.dashboard.suggestions.SuggestionAdapterV2;
import com.android.settings.dashboard.suggestions.SuggestionControllerMixin;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import com.android.settingslib.core.lifecycle.Lifecycle;
@@ -51,6 +50,7 @@ import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnSaveInstanceState;
import com.android.settingslib.drawer.DashboardCategory;
import com.android.settingslib.drawer.Tile;
import com.android.settingslib.suggestions.SuggestionControllerMixin;
import java.util.List;

View File

@@ -38,7 +38,6 @@ import com.android.settings.dashboard.conditional.ConditionManager;
import com.android.settings.dashboard.conditional.ConditionManager.ConditionListener;
import com.android.settings.dashboard.conditional.FocusRecyclerView;
import com.android.settings.dashboard.conditional.FocusRecyclerView.FocusListener;
import com.android.settings.dashboard.suggestions.SuggestionControllerMixin;
import com.android.settings.dashboard.suggestions.SuggestionDismissController;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.widget.ActionBarShadowController;
@@ -46,6 +45,7 @@ import com.android.settingslib.drawer.CategoryKey;
import com.android.settingslib.drawer.DashboardCategory;
import com.android.settingslib.drawer.SettingsDrawerActivity;
import com.android.settingslib.drawer.SettingsDrawerActivity.CategoryListener;
import com.android.settingslib.suggestions.SuggestionControllerMixin;
import com.android.settingslib.utils.ThreadUtils;
import java.util.List;
@@ -87,7 +87,9 @@ public class DashboardSummary extends InstrumentedFragment
super.onAttach(context);
Log.d(TAG, "Creating SuggestionControllerMixin");
mSuggestionControllerMixin = new SuggestionControllerMixin(context, this /* host */,
getLifecycle());
getLifecycle(), FeatureFactory.getFactory(context)
.getSuggestionFeatureProvider(context)
.getSuggestionServiceComponent());
}
@Override

View File

@@ -31,6 +31,7 @@ import com.android.settings.dashboard.DashboardAdapter.DashboardItemHolder;
import com.android.settings.dashboard.DashboardAdapter.IconCache;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import com.android.settingslib.suggestions.SuggestionControllerMixin;
import java.util.List;
import java.util.Objects;

View File

@@ -38,6 +38,7 @@ import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnSaveInstanceState;
import com.android.settingslib.suggestions.SuggestionControllerMixin;
import java.util.ArrayList;
import java.util.List;

View File

@@ -1,174 +0,0 @@
/*
* Copyright (C) 2017 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.dashboard.suggestions;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.service.settings.suggestions.ISuggestionService;
import android.service.settings.suggestions.Suggestion;
import android.support.annotation.Nullable;
import android.support.annotation.WorkerThread;
import android.util.Log;
import java.util.List;
/**
* A controller class to access suggestion data.
*/
public class SuggestionController {
/**
* Callback interface when service is connected/disconnected.
*/
public interface ServiceConnectionListener {
/**
* Called when service is connected.
*/
void onServiceConnected();
/**
* Called when service is disconnected.
*/
void onServiceDisconnected();
}
private static final String TAG = "SuggestionController";
private static final boolean DEBUG = false;
private final Context mContext;
private final Intent mServiceIntent;
private ServiceConnection mServiceConnection;
private ISuggestionService mRemoteService;
private ServiceConnectionListener mConnectionListener;
/**
* Create a new controller instance.
*
* @param context caller context
* @param service The component name for service.
* @param listener listener to receive service connected/disconnected event.
*/
public SuggestionController(Context context, ComponentName service,
ServiceConnectionListener listener) {
mContext = context.getApplicationContext();
mConnectionListener = listener;
mServiceIntent = new Intent().setComponent(service);
mServiceConnection = createServiceConnection();
}
/**
* Start the controller.
*/
public void start() {
mContext.bindServiceAsUser(mServiceIntent, mServiceConnection, Context.BIND_AUTO_CREATE,
android.os.Process.myUserHandle());
}
/**
* Stop the controller.
*/
public void stop() {
if (mRemoteService != null) {
mRemoteService = null;
mContext.unbindService(mServiceConnection);
}
}
/**
* Get setting suggestions.
*/
@Nullable
@WorkerThread
public List<Suggestion> getSuggestions() {
if (!isReady()) {
return null;
}
try {
return mRemoteService.getSuggestions();
} catch (NullPointerException e) {
Log.w(TAG, "mRemote service detached before able to query", e);
return null;
} catch (RemoteException e) {
Log.w(TAG, "Error when calling getSuggestion()", e);
return null;
}
}
public void dismissSuggestions(Suggestion suggestion) {
if (!isReady()) {
Log.w(TAG, "SuggestionController not ready, cannot dismiss " + suggestion.getId());
return;
}
try {
mRemoteService.dismissSuggestion(suggestion);
} catch (RemoteException e) {
Log.w(TAG, "Error when calling dismissSuggestion()", e);
}
}
public void launchSuggestion(Suggestion suggestion) {
if (!isReady()) {
Log.w(TAG, "SuggestionController not ready, cannot launch " + suggestion.getId());
return;
}
try {
mRemoteService.launchSuggestion(suggestion);
} catch (RemoteException e) {
Log.w(TAG, "Error when calling launchSuggestion()", e);
}
}
/**
* Whether or not the manager is ready
*/
private boolean isReady() {
return mRemoteService != null;
}
/**
* Create a new {@link ServiceConnection} object to handle service connect/disconnect event.
*/
private ServiceConnection createServiceConnection() {
return new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
if (DEBUG) {
Log.d(TAG, "Service is connected");
}
mRemoteService = ISuggestionService.Stub.asInterface(service);
if (mConnectionListener != null) {
mConnectionListener.onServiceConnected();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
if (mConnectionListener != null) {
mRemoteService = null;
mConnectionListener.onServiceDisconnected();
}
}
};
}
}

View File

@@ -1,139 +0,0 @@
/*
* Copyright (C) 2017 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.dashboard.suggestions;
import android.app.LoaderManager;
import android.content.Context;
import android.content.Loader;
import android.os.Bundle;
import android.service.settings.suggestions.Suggestion;
import android.support.annotation.Nullable;
import android.util.Log;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnStart;
import com.android.settingslib.core.lifecycle.events.OnStop;
import java.util.List;
/**
* Manages IPC communication to SettingsIntelligence for suggestion related services.
*/
public class SuggestionControllerMixin implements SuggestionController.ServiceConnectionListener,
LifecycleObserver, OnStart, OnStop, LoaderManager.LoaderCallbacks<List<Suggestion>> {
public interface SuggestionControllerHost {
/**
* Called when suggestion data fetching is ready.
*/
void onSuggestionReady(List<Suggestion> data);
/**
* Returns {@link LoaderManager} associated with the host. If host is not attached to
* activity then return null.
*/
@Nullable
LoaderManager getLoaderManager();
}
private static final String TAG = "SuggestionCtrlMixin";
private static final boolean DEBUG = false;
private final Context mContext;
private final SuggestionController mSuggestionController;
private final SuggestionControllerHost mHost;
private boolean mSuggestionLoaded;
public SuggestionControllerMixin(Context context, SuggestionControllerHost host,
Lifecycle lifecycle) {
mContext = context.getApplicationContext();
mHost = host;
mSuggestionController = new SuggestionController(mContext,
FeatureFactory.getFactory(mContext)
.getSuggestionFeatureProvider(mContext)
.getSuggestionServiceComponent(),
this /* serviceConnectionListener */);
if (lifecycle != null) {
lifecycle.addObserver(this);
}
}
@Override
public void onStart() {
mSuggestionController.start();
}
@Override
public void onStop() {
mSuggestionController.stop();
}
@Override
public void onServiceConnected() {
final LoaderManager loaderManager = mHost.getLoaderManager();
if (loaderManager != null) {
loaderManager.restartLoader(SuggestionLoader.LOADER_ID_SUGGESTIONS,
null /* args */, this /* callback */);
}
}
@Override
public void onServiceDisconnected() {
if (DEBUG) {
Log.d(TAG, "SuggestionService disconnected");
}
final LoaderManager loaderManager = mHost.getLoaderManager();
if (loaderManager != null) {
loaderManager.destroyLoader(SuggestionLoader.LOADER_ID_SUGGESTIONS);
}
}
@Override
public Loader<List<Suggestion>> onCreateLoader(int id, Bundle args) {
if (id == SuggestionLoader.LOADER_ID_SUGGESTIONS) {
mSuggestionLoaded = false;
return new SuggestionLoader(mContext, mSuggestionController);
}
throw new IllegalArgumentException("This loader id is not supported " + id);
}
@Override
public void onLoadFinished(Loader<List<Suggestion>> loader, List<Suggestion> data) {
mSuggestionLoaded = true;
mHost.onSuggestionReady(data);
}
@Override
public void onLoaderReset(Loader<List<Suggestion>> loader) {
mSuggestionLoaded = false;
}
public boolean isSuggestionLoaded() {
return mSuggestionLoaded;
}
public void dismissSuggestion(Suggestion suggestion) {
mSuggestionController.dismissSuggestions(suggestion);
}
public void launchSuggestion(Suggestion suggestion) {
mSuggestionController.launchSuggestion(suggestion);
}
}

View File

@@ -23,6 +23,7 @@ import android.support.v7.widget.helper.ItemTouchHelper;
import com.android.settings.R;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.suggestions.SuggestionControllerMixin;
/**
* Deprecated as a close button is provided to dismiss the suggestion.

View File

@@ -24,6 +24,7 @@ import android.support.annotation.NonNull;
import android.util.Pair;
import com.android.settingslib.drawer.Tile;
import com.android.settingslib.suggestions.SuggestionControllerMixin;
import java.util.List;

View File

@@ -40,6 +40,7 @@ import com.android.settings.wallpaper.WallpaperSuggestionActivity;
import com.android.settings.wifi.WifiCallingSuggestionActivity;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import com.android.settingslib.drawer.Tile;
import com.android.settingslib.suggestions.SuggestionControllerMixin;
import java.util.List;

View File

@@ -1,54 +0,0 @@
/*
* Copyright (C) 2017 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.dashboard.suggestions;
import android.content.Context;
import android.service.settings.suggestions.Suggestion;
import android.util.Log;
import com.android.settingslib.utils.AsyncLoader;
import java.util.List;
public class SuggestionLoader extends AsyncLoader<List<Suggestion>> {
public static final int LOADER_ID_SUGGESTIONS = 42;
private static final String TAG = "SuggestionLoader";
private final SuggestionController mSuggestionController;
public SuggestionLoader(Context context, SuggestionController controller) {
super(context);
mSuggestionController = controller;
}
@Override
protected void onDiscardResult(List<Suggestion> result) {
}
@Override
public List<Suggestion> loadInBackground() {
final List<Suggestion> data = mSuggestionController.getSuggestions();
if (data == null) {
Log.d(TAG, "data is null");
} else {
Log.d(TAG, "data size " + data.size());
}
return data;
}
}

View File

@@ -1,61 +0,0 @@
/*
* Copyright (C) 2017 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.dashboard.suggestions;
import android.service.settings.suggestions.Suggestion;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import java.util.List;
@Implements(SuggestionController.class)
public class ShadowSuggestionController {
public static boolean sStartCalled;
public static boolean sStopCalled;
public static boolean sGetSuggestionCalled;
public static List<Suggestion> sSuggestions;
public static void reset() {
sStartCalled = false;
sStopCalled = false;
sGetSuggestionCalled = false;
sSuggestions = null;
}
@Implementation
public void start() {
sStartCalled = true;
}
@Implementation
public void stop() {
sStopCalled = true;
}
public static void setSuggestion(List<Suggestion> suggestions) {
sSuggestions = suggestions;
}
@Implementation
public List<Suggestion> getSuggestions() {
sGetSuggestionCalled = true;
return sSuggestions;
}
}

View File

@@ -36,6 +36,7 @@ import com.android.settings.TestConfig;
import com.android.settings.dashboard.DashboardAdapter;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settingslib.suggestions.SuggestionControllerMixin;
import org.junit.Before;
import org.junit.Test;

View File

@@ -36,6 +36,7 @@ import com.android.settings.TestConfig;
import com.android.settings.dashboard.DashboardAdapterV2;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settingslib.suggestions.SuggestionControllerMixin;
import org.junit.Before;
import org.junit.Test;

View File

@@ -1,128 +0,0 @@
/*
* Copyright (C) 2017 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.dashboard.suggestions;
import static android.arch.lifecycle.Lifecycle.Event.ON_START;
import static android.arch.lifecycle.Lifecycle.Event.ON_STOP;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.LoaderManager;
import android.arch.lifecycle.LifecycleOwner;
import android.content.Context;
import com.android.settings.TestConfig;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settingslib.core.lifecycle.Lifecycle;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION,
shadows = {
ShadowSuggestionController.class
})
public class SuggestionControllerMixinTest {
@Mock
private SuggestionControllerMixin.SuggestionControllerHost mHost;
private Context mContext;
private LifecycleOwner mLifecycleOwner;
private Lifecycle mLifecycle;
private SuggestionControllerMixin mMixin;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
FakeFeatureFactory.setupForTest();
mLifecycleOwner = () -> mLifecycle;
mLifecycle = new Lifecycle(mLifecycleOwner);
}
@After
public void tearDown() {
ShadowSuggestionController.reset();
}
@Test
public void goThroughLifecycle_onStartStop_shouldStartStopController() {
mMixin = new SuggestionControllerMixin(mContext, mHost, mLifecycle);
mLifecycle.handleLifecycleEvent(ON_START);
assertThat(ShadowSuggestionController.sStartCalled).isTrue();
mLifecycle.handleLifecycleEvent(ON_STOP);
assertThat(ShadowSuggestionController.sStopCalled).isTrue();
}
@Test
public void onServiceConnected_shouldGetSuggestion() {
final LoaderManager loaderManager = mock(LoaderManager.class);
when(mHost.getLoaderManager()).thenReturn(loaderManager);
mMixin = new SuggestionControllerMixin(mContext, mHost, mLifecycle);
mMixin.onServiceConnected();
verify(loaderManager).restartLoader(SuggestionLoader.LOADER_ID_SUGGESTIONS,
null /* args */, mMixin /* callback */);
}
@Test
public void onServiceConnected_hostNotAttached_shouldDoNothing() {
when(mHost.getLoaderManager()).thenReturn(null);
mMixin = new SuggestionControllerMixin(mContext, mHost, mLifecycle);
mMixin.onServiceConnected();
verify(mHost).getLoaderManager();
}
@Test
public void onServiceDisconnected_hostNotAttached_shouldDoNothing() {
when(mHost.getLoaderManager()).thenReturn(null);
mMixin = new SuggestionControllerMixin(mContext, mHost, mLifecycle);
mMixin.onServiceDisconnected();
verify(mHost).getLoaderManager();
}
@Test
public void doneLoadingg_shouldSetSuggestionLoaded() {
mMixin = new SuggestionControllerMixin(mContext, mHost, mLifecycle);
mMixin.onLoadFinished(mock(SuggestionLoader.class), null);
assertThat(mMixin.isSuggestionLoaded()).isTrue();
mMixin.onLoaderReset(mock(SuggestionLoader.class));
assertThat(mMixin.isSuggestionLoaded()).isFalse();
}
}

View File

@@ -33,6 +33,7 @@ import com.android.settings.R;
import com.android.settings.TestConfig;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settingslib.suggestions.SuggestionControllerMixin;
import org.junit.Before;
import org.junit.Test;

View File

@@ -44,6 +44,7 @@ import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.SettingsShadowResources;
import com.android.settings.testutils.shadow.ShadowSecureSettings;
import com.android.settingslib.drawer.Tile;
import com.android.settingslib.suggestions.SuggestionControllerMixin;
import org.junit.After;
import org.junit.Before;