/*
|
* Copyright (C) 2016 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.systemui.fragments;
|
|
import android.app.Fragment;
|
import android.content.res.Configuration;
|
import android.os.Handler;
|
import android.util.ArrayMap;
|
import android.view.View;
|
|
import com.android.systemui.ConfigurationChangedReceiver;
|
import com.android.systemui.Dumpable;
|
import com.android.systemui.SystemUIFactory;
|
import com.android.systemui.qs.QSFragment;
|
import com.android.systemui.statusbar.phone.NavigationBarFragment;
|
|
import java.io.FileDescriptor;
|
import java.io.PrintWriter;
|
import java.lang.reflect.Method;
|
import java.lang.reflect.Modifier;
|
|
import javax.inject.Inject;
|
import javax.inject.Singleton;
|
|
import dagger.Subcomponent;
|
|
/**
|
* Holds a map of root views to FragmentHostStates and generates them as needed.
|
* Also dispatches the configuration changes to all current FragmentHostStates.
|
*/
|
@Singleton
|
public class FragmentService implements ConfigurationChangedReceiver, Dumpable {
|
|
private static final String TAG = "FragmentService";
|
|
private final ArrayMap<View, FragmentHostState> mHosts = new ArrayMap<>();
|
private final ArrayMap<String, Method> mInjectionMap = new ArrayMap<>();
|
private final Handler mHandler = new Handler();
|
private final FragmentCreator mFragmentCreator;
|
|
@Inject
|
public FragmentService(SystemUIFactory.SystemUIRootComponent rootComponent) {
|
mFragmentCreator = rootComponent.createFragmentCreator();
|
initInjectionMap();
|
}
|
|
ArrayMap<String, Method> getInjectionMap() {
|
return mInjectionMap;
|
}
|
|
FragmentCreator getFragmentCreator() {
|
return mFragmentCreator;
|
}
|
|
private void initInjectionMap() {
|
for (Method method : FragmentCreator.class.getDeclaredMethods()) {
|
if (Fragment.class.isAssignableFrom(method.getReturnType())
|
&& (method.getModifiers() & Modifier.PUBLIC) != 0) {
|
mInjectionMap.put(method.getReturnType().getName(), method);
|
}
|
}
|
}
|
|
public FragmentHostManager getFragmentHostManager(View view) {
|
View root = view.getRootView();
|
FragmentHostState state = mHosts.get(root);
|
if (state == null) {
|
state = new FragmentHostState(root);
|
mHosts.put(root, state);
|
}
|
return state.getFragmentHostManager();
|
}
|
|
public void removeAndDestroy(View view) {
|
final FragmentHostState state = mHosts.remove(view.getRootView());
|
if (state != null) {
|
state.mFragmentHostManager.destroy();
|
}
|
}
|
|
public void destroyAll() {
|
for (FragmentHostState state : mHosts.values()) {
|
state.mFragmentHostManager.destroy();
|
}
|
}
|
|
@Override
|
public void onConfigurationChanged(Configuration newConfig) {
|
for (FragmentHostState state : mHosts.values()) {
|
state.sendConfigurationChange(newConfig);
|
}
|
}
|
|
@Override
|
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
|
pw.println("Dumping fragments:");
|
for (FragmentHostState state : mHosts.values()) {
|
state.mFragmentHostManager.getFragmentManager().dump(" ", fd, pw, args);
|
}
|
}
|
|
/**
|
* The subcomponent of dagger that holds all fragments that need injection.
|
*/
|
@Subcomponent
|
public interface FragmentCreator {
|
/**
|
* Inject a NavigationBarFragment.
|
*/
|
NavigationBarFragment createNavigationBarFragment();
|
/**
|
* Inject a QSFragment.
|
*/
|
QSFragment createQSFragment();
|
}
|
|
private class FragmentHostState {
|
private final View mView;
|
|
private FragmentHostManager mFragmentHostManager;
|
|
public FragmentHostState(View view) {
|
mView = view;
|
mFragmentHostManager = new FragmentHostManager(FragmentService.this, mView);
|
}
|
|
public void sendConfigurationChange(Configuration newConfig) {
|
mHandler.post(() -> handleSendConfigurationChange(newConfig));
|
}
|
|
public FragmentHostManager getFragmentHostManager() {
|
return mFragmentHostManager;
|
}
|
|
private void handleSendConfigurationChange(Configuration newConfig) {
|
mFragmentHostManager.onConfigurationChanged(newConfig);
|
}
|
}
|
}
|