/*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html.
*
* This file is a derivative of code released under the terms listed below.
*
*/
/*
* Copyright (c) 2013,
* Tobias Blaschke <code@tobiasblaschke.de>
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The names of the contributors may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package com.ibm.wala.dalvik.util.androidEntryPoints;
import java.util.List;
import com.ibm.wala.dalvik.util.AndroidEntryPointLocator.AndroidPossibleEntryPoint;
import com.ibm.wala.dalvik.ipa.callgraph.impl.AndroidEntryPoint.ExecutionOrder;
import com.ibm.wala.dalvik.ipa.callgraph.impl.AndroidEntryPoint;
import com.ibm.wala.dalvik.util.androidEntryPoints.ActivityEP;
import com.ibm.wala.dalvik.util.AndroidComponent;
/**
* Hardcoded EntryPoint-specifications for an Android-Activity.
*
* The specifications are read and handled by AndroidEntryPointLocator.
* https://developer.android.com/reference/android/app/Fragment.html
*
* @see com.ibm.wala.dalvik.util.AndroidEntryPointLocator
* @author Tobias Blaschke <code@tobiasblaschke.de>
*/
public final class FragmentEP {
//
// Start-up sequence:
//
/**
* called once the fragment is associated with its activity.
*
* Called before onCreate
*/
public static final AndroidPossibleEntryPoint onAttach = new AndroidPossibleEntryPoint(AndroidComponent.FRAGMENT,
"onAttach",
ExecutionOrder.between(
new AndroidEntryPoint.IExecutionOrder[] {
ExecutionOrder.AT_FIRST,
ApplicationEP.onCreate,
ProviderEP.onCreate
//ActivityEP.onCreate // I's same time...
},
new AndroidEntryPoint.IExecutionOrder[] {
ExecutionOrder.START_OF_LOOP,
//ServiceEP.onCreate // Shall we put that there?
}
));
/**
* called to do initial creation of the fragment.
*
* Called before before onCreateView.
* Note that this can be called while the fragment's activity is still in the process of being created.
* once the activity itself is created: onActivityCreated(Bundle).
*/
public static final AndroidPossibleEntryPoint onCreate = new AndroidPossibleEntryPoint(AndroidComponent.FRAGMENT,
"onCreate",
ExecutionOrder.between(
new AndroidEntryPoint.IExecutionOrder[] {
ExecutionOrder.AT_FIRST,
onAttach,
//ActivityEP.onCreate // I's same time...
},
new AndroidEntryPoint.IExecutionOrder[] {
ExecutionOrder.START_OF_LOOP,
}
));
/**
* creates and returns the view hierarchy associated with the fragment.
*
* This will be called between onCreate(Bundle) and onActivityCreated(Bundle). XXX: CONTRADICTING DOCUMENTATION!
* his is optional, and non-graphical fragments can return null.
*/
public static final AndroidPossibleEntryPoint onCreateView = new AndroidPossibleEntryPoint(AndroidComponent.FRAGMENT,
"onCreateView",
ExecutionOrder.between(
new AndroidEntryPoint.IExecutionOrder[] {
ExecutionOrder.AT_FIRST,
onCreate,
//ActivityEP.onCreate // May still be same time...
},
new AndroidEntryPoint.IExecutionOrder[] {
ExecutionOrder.START_OF_LOOP,
}
));
/**
* tells the fragment that its activity has completed its own Activity.onCreate().
*
* Called when the fragment's activity has been created and this fragment's view hierarchy instantiated.
* This is called after onCreateView XXX: CONTRADICTING DOCUMENTATION!
* and before onViewStateRestored(Bundle).
*/
public static final AndroidPossibleEntryPoint onActivityCreated = new AndroidPossibleEntryPoint(AndroidComponent.FRAGMENT,
"onActivityCreated",
ExecutionOrder.between(
new AndroidEntryPoint.IExecutionOrder[] {
ExecutionOrder.AT_FIRST,
onCreate,
onCreateView // XXX: Now which one is correct?
},
new AndroidEntryPoint.IExecutionOrder[] {
ExecutionOrder.START_OF_LOOP,
//onCreateView // XXX: Now which one is correct?
}
));
/**
* tells the fragment that all of the saved state of its view hierarchy has been restored.
*
* Called when all saved state has been restored into the view hierarchy of the fragment.
* This is called after onActivityCreated(Bundle) and before onStart().
*/
public static final AndroidPossibleEntryPoint onViewStateRestored = new AndroidPossibleEntryPoint(AndroidComponent.FRAGMENT,
"onViewStateRestored",
ExecutionOrder.between(
new AndroidEntryPoint.IExecutionOrder[] {
ExecutionOrder.AT_FIRST, // TODO: Already Part of loop?
onCreateView,
onActivityCreated
},
new AndroidEntryPoint.IExecutionOrder[] {
ExecutionOrder.START_OF_LOOP,
// TODO: Start of the Activity at this point?
}
));
/**
* makes the fragment visible to the user (based on its containing activity being started).
*
* Called when the Fragment is visible to the user.
* This is generally tied to Activity.onStart of the containing Activity's lifecycle.
*/
public static final AndroidPossibleEntryPoint onStart = new AndroidPossibleEntryPoint(AndroidComponent.FRAGMENT,
"onStart",
ExecutionOrder.between(
new AndroidEntryPoint.IExecutionOrder[] {
ExecutionOrder.START_OF_LOOP,
ActivityEP.onStart, // TODO: Verify
onViewStateRestored
},
new AndroidEntryPoint.IExecutionOrder[] {
ExecutionOrder.MIDDLE_OF_LOOP
}
));
/**
* makes the fragment interacting with the user (based on its containing activity being resumed).
*
* Called when the fragment is visible to the user and actively running.
* This is generally tied to Activity.onResume of the containing Activity's lifecycle.
*/
public static final AndroidPossibleEntryPoint onResume = new AndroidPossibleEntryPoint(AndroidComponent.FRAGMENT,
"onResume",
ExecutionOrder.between(
new AndroidEntryPoint.IExecutionOrder[] {
ExecutionOrder.START_OF_LOOP,
onStart,
ActivityEP.onPostCreate,
ActivityEP.onRestoreInstanceState,
ActivityEP.onResume // TODO: Rather after or before?
},
new AndroidEntryPoint.IExecutionOrder[] {
ExecutionOrder.MIDDLE_OF_LOOP
}
));
//
// Stop sequence
//
/**
* fragment is no longer interacting with the user either because its activity is being paused or a fragment operation
* is modifying it in the activity.
*
* Called when the Fragment is no longer resumed.
* This is generally tied to Activity.onPause of the containing Activity's lifecycle.
*/
public static final AndroidPossibleEntryPoint onPause = new AndroidPossibleEntryPoint(AndroidComponent.FRAGMENT,
"onPause",
ExecutionOrder.between(
new AndroidEntryPoint.IExecutionOrder[] {
ExecutionOrder.END_OF_LOOP,
ActivityEP.onPause // TODO: Rather after or before?
},
new AndroidEntryPoint.IExecutionOrder[] {
ExecutionOrder.AFTER_LOOP
}
));
/**
* fragment is no longer visible to the user either because its activity is being stopped or a fragment operation is
* modifying it in the activity.
*
* Called when the Fragment is no longer started.
* This is generally tied to Activity.onStop of the containing Activity's lifecycle.
*/
public static final AndroidPossibleEntryPoint onStop = new AndroidPossibleEntryPoint(AndroidComponent.FRAGMENT,
"onStop",
ExecutionOrder.after(
new AndroidEntryPoint.IExecutionOrder[] {
onPause,
ActivityEP.onStop // TODO: Rather after or before?
}
));
/**
* allows the fragment to clean up resources associated with its View.
*
* Called when the view previously created by onCreateView(LayoutInflater, ViewGroup, Bundle) has been detached from the fragment.
* This is called after onStop() and before onDestroy(). It is called regardless of whether onCreateView returned a non-null view.
*
* Internally it is called after the view's state has been saved but before it has been removed from its parent.
*/
public static final AndroidPossibleEntryPoint onDestroyView = new AndroidPossibleEntryPoint(AndroidComponent.FRAGMENT,
"onDestroyView",
ExecutionOrder.after(
new AndroidEntryPoint.IExecutionOrder[] {
onStop,
ActivityEP.onStop // TODO: Rather after or before?
}
));
/**
* called to do final cleanup of the fragment's state.
*
* Called when the fragment is no longer in use. This is called after onStop() and before onDetach().
*/
public static final AndroidPossibleEntryPoint onDestroy = new AndroidPossibleEntryPoint(AndroidComponent.FRAGMENT,
"onDestroy",
ExecutionOrder.after(
new AndroidEntryPoint.IExecutionOrder[] {
onDestroyView,
ActivityEP.onStop // TODO: Rather after or before?
}
));
/**
* called immediately prior to the fragment no longer being associated with its activity.
*
* Called when the fragment is no longer attached to its activity. This is called after onDestroy().
*/
public static final AndroidPossibleEntryPoint onDetach = new AndroidPossibleEntryPoint(AndroidComponent.FRAGMENT,
"onDetach",
ExecutionOrder.between(
new AndroidEntryPoint.IExecutionOrder[] {
ExecutionOrder.AT_LAST,
onDestroy
},
new AndroidEntryPoint.IExecutionOrder[] {
ActivityEP.onDestroy
}
));
//
// Misc
//
/**
* @see ActivityEP.onActivityResult
*/
public static final AndroidPossibleEntryPoint onActivityResult = new AndroidPossibleEntryPoint(AndroidComponent.FRAGMENT,
"onActivityResult",
ExecutionOrder.after(
new AndroidEntryPoint.IExecutionOrder[] {
ExecutionOrder.MULTIPLE_TIMES_IN_LOOP,
// If this Activity starts an notherone it most certainly goes into background so
// place this after onPause
onPause,
ActivityEP.onPause,
//ActivityEP.onActivityResult // TODO: Resolve if to put here...
}
));
/**
* Unlike activities, other components are never restarted.
*/
public static final AndroidPossibleEntryPoint onConfigurationChanged = new AndroidPossibleEntryPoint(AndroidComponent.FRAGMENT,
"onConfigurationChanged",
ExecutionOrder.directlyAfter(ActivityEP.onConfigurationChanged) // TODO: Verify
);
/**
* This hook is called whenever an item in a context menu is selected.
*/
public static final AndroidPossibleEntryPoint onContextItemSelected = new AndroidPossibleEntryPoint(AndroidComponent.FRAGMENT,
"onContextItemSelected",
ExecutionOrder.directlyAfter(ActivityEP.onContextItemSelected) // TODO: Verify
);
/**
* Called when a fragment loads an animation.
*/
public static final AndroidPossibleEntryPoint onCreateAnimator = new AndroidPossibleEntryPoint(AndroidComponent.FRAGMENT,
"onCreateAnimator",
ExecutionOrder.directlyAfter(onResume) // TODO: Here?
);
/**
* Called when a context menu for the view is about to be shown.
*
* Unlike onCreateOptionsMenu, this will be called every time the context menu is about to be shown
*/
public static final AndroidPossibleEntryPoint onCreateContextMenu = new AndroidPossibleEntryPoint(AndroidComponent.FRAGMENT,
"onCreateContextMenu",
ExecutionOrder.directlyAfter(ActivityEP.onCreateContextMenu)
);
/**
* Initialize the contents of the Activity's standard options menu.
*/
public static final AndroidPossibleEntryPoint onCreateOptionsMenu = new AndroidPossibleEntryPoint(AndroidComponent.FRAGMENT,
"onCreateOptionsMenu",
ExecutionOrder.directlyAfter(ActivityEP.onCreateOptionsMenu)
);
/**
* Called when this fragment's option menu items are no longer being included in the overall options menu.
* Receiving this call means that the menu needed to be rebuilt, but this fragment's items were not included in the newly
* built menu (its onCreateOptionsMenu was not called).
*/
public static final AndroidPossibleEntryPoint onDestroyOptionsMenu = new AndroidPossibleEntryPoint(AndroidComponent.FRAGMENT,
"onDestroyOptionsMenu",
ExecutionOrder.after(
new AndroidEntryPoint.IExecutionOrder[] {
ExecutionOrder.END_OF_LOOP, // TODO: Here?
}
));
/**
* Called when the hidden state has changed.
*
* Fragments start out not hidden.
*/
public static final AndroidPossibleEntryPoint onHiddenChanged = new AndroidPossibleEntryPoint(AndroidComponent.FRAGMENT,
"onHiddenChanged",
ExecutionOrder.after(
new AndroidEntryPoint.IExecutionOrder[] {
ExecutionOrder.MIDDLE_OF_LOOP, // TODO: Here?
}
));
/**
* Called when a fragment is being created as part of a view layout inflation, typically from setting the content view of an
* activity.
*
* This may be called immediately after the fragment is created from a tag in a layout file.
* Note this is before the fragment's onAttach(Activity) has been called...
*/
public static final AndroidPossibleEntryPoint onInflate = new AndroidPossibleEntryPoint(AndroidComponent.FRAGMENT,
"onInflate",
ExecutionOrder.between(
new AndroidEntryPoint.IExecutionOrder[] {
ExecutionOrder.AT_FIRST,
ApplicationEP.onCreate, // TODO: Here?
ActivityEP.onCreate
},
new AndroidEntryPoint.IExecutionOrder[] {
onAttach
}
));
/**
* @see ActivityEP.onLowMemory
* @see ApplicationEP.onLowMemory
*/
public static final AndroidPossibleEntryPoint onLowMemory = new AndroidPossibleEntryPoint(AndroidComponent.FRAGMENT,
"onLowMemory",
ExecutionOrder.directlyBefore(ActivityEP.onLowMemory)
);
/**
* @see ActivityEP.onOptionsItemSelected
*/
public static final AndroidPossibleEntryPoint onOptionsItemSelected = new AndroidPossibleEntryPoint(AndroidComponent.FRAGMENT,
"onOptionsItemSelected",
ExecutionOrder.directlyAfter(ActivityEP.onOptionsItemSelected) // TODO: After? Before?
);
/**
* @see ActivityEP.onOptionsMenuClosed
*/
public static final AndroidPossibleEntryPoint onOptionsMenuClosed = new AndroidPossibleEntryPoint(AndroidComponent.FRAGMENT,
"onOptionsMenuClosed",
ExecutionOrder.directlyAfter(ActivityEP.onOptionsMenuClosed) // TODO: After? Before?
);
/**
* This is called right before the menu is shown, every time it is shown.
*
* @see ActivityEP.onPrepareOptionsMenu
*/
public static final AndroidPossibleEntryPoint onPrepareOptionsMenu = new AndroidPossibleEntryPoint(AndroidComponent.FRAGMENT,
"onPrepareOptionsMenu",
ExecutionOrder.between(
new AndroidEntryPoint.IExecutionOrder[] {
ExecutionOrder.START_OF_LOOP,
onCreateOptionsMenu,
onResume
},
new AndroidEntryPoint.IExecutionOrder[] {
onOptionsItemSelected,
onOptionsMenuClosed,
ExecutionOrder.AFTER_LOOP
}
));
/**
* Called to ask the fragment to save its current dynamic state.
*
* Bundle here will be available in the Bundle given to onCreate(Bundle), onCreateView(LayoutInflater, ViewGroup, Bundle),
* and onActivityCreated(Bundle).
*
* This method may be called at any time before onDestroy(). There are many situations where a fragment may be mostly torn down,
* but its state will not be saved until its owning activity actually needs to save its state.
*/
public static final AndroidPossibleEntryPoint onSaveInstanceState = new AndroidPossibleEntryPoint(AndroidComponent.FRAGMENT,
"onSaveInstanceState",
ExecutionOrder.between(
new AndroidEntryPoint.IExecutionOrder[] {
onStop,
onDestroyView // See comment there
},
new AndroidEntryPoint.IExecutionOrder[] {
onDestroy,
ExecutionOrder.AT_LAST // XXX: To early
}
));
/**
* @see ActtivityEP.onTrimMemory
*/
public static final AndroidPossibleEntryPoint onTrimMemory = new AndroidPossibleEntryPoint(AndroidComponent.FRAGMENT,
"onTrimMemory",
ExecutionOrder.directlyBefore(ActivityEP.onTrimMemory)
);
/**
* Called immediately after onCreateView has returned, but before any saved state has been restored in to the view.
*/
public static final AndroidPossibleEntryPoint onViewCreated = new AndroidPossibleEntryPoint(AndroidComponent.FRAGMENT,
"onViewCreated",
ExecutionOrder.between(
onCreateView,
new AndroidEntryPoint.IExecutionOrder[] {
onActivityCreated,
onViewStateRestored
}
));
/**
* Add the EntryPoint specifications defined in this file to the given list.
*
* @param possibleEntryPoints the list to extend.
*/
public static void populate(List<? super AndroidPossibleEntryPoint> possibleEntryPoints) {
possibleEntryPoints.add(onAttach);
possibleEntryPoints.add(onCreate);
possibleEntryPoints.add(onCreateView);
possibleEntryPoints.add(onActivityCreated);
possibleEntryPoints.add(onViewStateRestored);
possibleEntryPoints.add(onStart);
possibleEntryPoints.add(onResume);
possibleEntryPoints.add(onPause);
possibleEntryPoints.add(onStop);
possibleEntryPoints.add(onDestroyView);
possibleEntryPoints.add(onDestroy);
possibleEntryPoints.add(onDetach);
possibleEntryPoints.add(onActivityResult);
possibleEntryPoints.add(onConfigurationChanged);
possibleEntryPoints.add(onContextItemSelected);
possibleEntryPoints.add(onCreateAnimator);
possibleEntryPoints.add(onCreateContextMenu);
possibleEntryPoints.add(onCreateOptionsMenu);
possibleEntryPoints.add(onDestroyOptionsMenu);
possibleEntryPoints.add(onHiddenChanged);
possibleEntryPoints.add(onInflate);
possibleEntryPoints.add(onLowMemory);
possibleEntryPoints.add(onOptionsItemSelected);
possibleEntryPoints.add(onOptionsMenuClosed);
possibleEntryPoints.add(onPrepareOptionsMenu);
possibleEntryPoints.add(onSaveInstanceState);
possibleEntryPoints.add(onTrimMemory);
possibleEntryPoints.add(onViewCreated);
}
}