Merge "[RenderScript] typo fix in rs BLAS jni, to correctly handle complex params." into mnc-dev
diff --git a/api/current.txt b/api/current.txt
index fc869ad..be01112 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -4328,9 +4328,11 @@
method public boolean getAllowReturnTransitionOverlap();
method public final android.os.Bundle getArguments();
method public final android.app.FragmentManager getChildFragmentManager();
+ method public android.content.Context getContext();
method public android.transition.Transition getEnterTransition();
method public android.transition.Transition getExitTransition();
method public final android.app.FragmentManager getFragmentManager();
+ method public final java.lang.Object getHost();
method public final int getId();
method public android.app.LoaderManager getLoaderManager();
method public final android.app.Fragment getParentFragment();
@@ -4360,7 +4362,8 @@
method public final boolean isVisible();
method public void onActivityCreated(android.os.Bundle);
method public void onActivityResult(int, int, android.content.Intent);
- method public void onAttach(android.app.Activity);
+ method public void onAttach(android.content.Context);
+ method public deprecated void onAttach(android.app.Activity);
method public void onConfigurationChanged(android.content.res.Configuration);
method public boolean onContextItemSelected(android.view.MenuItem);
method public void onCreate(android.os.Bundle);
@@ -4374,7 +4377,8 @@
method public void onDetach();
method public void onHiddenChanged(boolean);
method public deprecated void onInflate(android.util.AttributeSet, android.os.Bundle);
- method public void onInflate(android.app.Activity, android.util.AttributeSet, android.os.Bundle);
+ method public void onInflate(android.content.Context, android.util.AttributeSet, android.os.Bundle);
+ method public deprecated void onInflate(android.app.Activity, android.util.AttributeSet, android.os.Bundle);
method public void onLowMemory();
method public boolean onOptionsItemSelected(android.view.MenuItem);
method public void onOptionsMenuClosed(android.view.Menu);
@@ -4441,6 +4445,64 @@
method public abstract boolean onBreadCrumbClick(android.app.FragmentManager.BackStackEntry, int);
}
+ public abstract class FragmentContainer {
+ ctor public FragmentContainer();
+ method public abstract android.view.View onFindViewById(int);
+ method public abstract boolean onHasView();
+ }
+
+ public class FragmentController {
+ method public void attachHost(android.app.Fragment);
+ method public static final android.app.FragmentController createController(android.app.FragmentHostCallback<?>);
+ method public void dispatchActivityCreated();
+ method public void dispatchConfigurationChanged(android.content.res.Configuration);
+ method public boolean dispatchContextItemSelected(android.view.MenuItem);
+ method public void dispatchCreate();
+ method public boolean dispatchCreateOptionsMenu(android.view.Menu, android.view.MenuInflater);
+ method public void dispatchDestroy();
+ method public void dispatchDestroyView();
+ method public void dispatchLowMemory();
+ method public boolean dispatchOptionsItemSelected(android.view.MenuItem);
+ method public void dispatchOptionsMenuClosed(android.view.Menu);
+ method public void dispatchPause();
+ method public boolean dispatchPrepareOptionsMenu(android.view.Menu);
+ method public void dispatchResume();
+ method public void dispatchStart();
+ method public void dispatchStop();
+ method public void dispatchTrimMemory(int);
+ method public void doLoaderDestroy();
+ method public void doLoaderStart();
+ method public void doLoaderStop(boolean);
+ method public void dumpLoaders(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
+ method public boolean execPendingActions();
+ method public android.app.Fragment findFragmentByWho(java.lang.String);
+ method public android.app.FragmentManager getFragmentManager();
+ method public android.app.LoaderManager getLoaderManager();
+ method public void noteStateNotSaved();
+ method public android.view.View onCreateView(android.view.View, java.lang.String, android.content.Context, android.util.AttributeSet);
+ method public void reportLoaderStart();
+ method public void restoreAllState(android.os.Parcelable, java.util.List<android.app.Fragment>);
+ method public void restoreLoaderNonConfig(android.util.ArrayMap<java.lang.String, android.app.LoaderManager>);
+ method public android.util.ArrayMap<java.lang.String, android.app.LoaderManager> retainLoaderNonConfig();
+ method public java.util.List<android.app.Fragment> retainNonConfig();
+ method public android.os.Parcelable saveAllState();
+ }
+
+ public abstract class FragmentHostCallback extends android.app.FragmentContainer {
+ ctor public FragmentHostCallback(android.content.Context, android.os.Handler, int);
+ method public void onDump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
+ method public android.view.View onFindViewById(int);
+ method public abstract E onGetHost();
+ method public android.view.LayoutInflater onGetLayoutInflater();
+ method public int onGetWindowAnimations();
+ method public boolean onHasView();
+ method public boolean onHasWindowAnimations();
+ method public void onInvalidateOptionsMenu();
+ method public boolean onShouldSaveFragmentState(android.app.Fragment);
+ method public void onStartActivityFromFragment(android.app.Fragment, android.content.Intent, int, android.os.Bundle);
+ method public boolean onUseFragmentManagerInflaterFactory();
+ }
+
public abstract class FragmentManager {
ctor public FragmentManager();
method public abstract void addOnBackStackChangedListener(android.app.FragmentManager.OnBackStackChangedListener);
diff --git a/api/system-current.txt b/api/system-current.txt
index 5416ef6..c4f96af 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -4418,9 +4418,11 @@
method public boolean getAllowReturnTransitionOverlap();
method public final android.os.Bundle getArguments();
method public final android.app.FragmentManager getChildFragmentManager();
+ method public android.content.Context getContext();
method public android.transition.Transition getEnterTransition();
method public android.transition.Transition getExitTransition();
method public final android.app.FragmentManager getFragmentManager();
+ method public final java.lang.Object getHost();
method public final int getId();
method public android.app.LoaderManager getLoaderManager();
method public final android.app.Fragment getParentFragment();
@@ -4450,7 +4452,8 @@
method public final boolean isVisible();
method public void onActivityCreated(android.os.Bundle);
method public void onActivityResult(int, int, android.content.Intent);
- method public void onAttach(android.app.Activity);
+ method public void onAttach(android.content.Context);
+ method public deprecated void onAttach(android.app.Activity);
method public void onConfigurationChanged(android.content.res.Configuration);
method public boolean onContextItemSelected(android.view.MenuItem);
method public void onCreate(android.os.Bundle);
@@ -4464,7 +4467,8 @@
method public void onDetach();
method public void onHiddenChanged(boolean);
method public deprecated void onInflate(android.util.AttributeSet, android.os.Bundle);
- method public void onInflate(android.app.Activity, android.util.AttributeSet, android.os.Bundle);
+ method public void onInflate(android.content.Context, android.util.AttributeSet, android.os.Bundle);
+ method public deprecated void onInflate(android.app.Activity, android.util.AttributeSet, android.os.Bundle);
method public void onLowMemory();
method public boolean onOptionsItemSelected(android.view.MenuItem);
method public void onOptionsMenuClosed(android.view.Menu);
@@ -4531,6 +4535,64 @@
method public abstract boolean onBreadCrumbClick(android.app.FragmentManager.BackStackEntry, int);
}
+ public abstract class FragmentContainer {
+ ctor public FragmentContainer();
+ method public abstract android.view.View onFindViewById(int);
+ method public abstract boolean onHasView();
+ }
+
+ public class FragmentController {
+ method public void attachHost(android.app.Fragment);
+ method public static final android.app.FragmentController createController(android.app.FragmentHostCallback<?>);
+ method public void dispatchActivityCreated();
+ method public void dispatchConfigurationChanged(android.content.res.Configuration);
+ method public boolean dispatchContextItemSelected(android.view.MenuItem);
+ method public void dispatchCreate();
+ method public boolean dispatchCreateOptionsMenu(android.view.Menu, android.view.MenuInflater);
+ method public void dispatchDestroy();
+ method public void dispatchDestroyView();
+ method public void dispatchLowMemory();
+ method public boolean dispatchOptionsItemSelected(android.view.MenuItem);
+ method public void dispatchOptionsMenuClosed(android.view.Menu);
+ method public void dispatchPause();
+ method public boolean dispatchPrepareOptionsMenu(android.view.Menu);
+ method public void dispatchResume();
+ method public void dispatchStart();
+ method public void dispatchStop();
+ method public void dispatchTrimMemory(int);
+ method public void doLoaderDestroy();
+ method public void doLoaderStart();
+ method public void doLoaderStop(boolean);
+ method public void dumpLoaders(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
+ method public boolean execPendingActions();
+ method public android.app.Fragment findFragmentByWho(java.lang.String);
+ method public android.app.FragmentManager getFragmentManager();
+ method public android.app.LoaderManager getLoaderManager();
+ method public void noteStateNotSaved();
+ method public android.view.View onCreateView(android.view.View, java.lang.String, android.content.Context, android.util.AttributeSet);
+ method public void reportLoaderStart();
+ method public void restoreAllState(android.os.Parcelable, java.util.List<android.app.Fragment>);
+ method public void restoreLoaderNonConfig(android.util.ArrayMap<java.lang.String, android.app.LoaderManager>);
+ method public android.util.ArrayMap<java.lang.String, android.app.LoaderManager> retainLoaderNonConfig();
+ method public java.util.List<android.app.Fragment> retainNonConfig();
+ method public android.os.Parcelable saveAllState();
+ }
+
+ public abstract class FragmentHostCallback extends android.app.FragmentContainer {
+ ctor public FragmentHostCallback(android.content.Context, android.os.Handler, int);
+ method public void onDump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
+ method public android.view.View onFindViewById(int);
+ method public abstract E onGetHost();
+ method public android.view.LayoutInflater onGetLayoutInflater();
+ method public int onGetWindowAnimations();
+ method public boolean onHasView();
+ method public boolean onHasWindowAnimations();
+ method public void onInvalidateOptionsMenu();
+ method public boolean onShouldSaveFragmentState(android.app.Fragment);
+ method public void onStartActivityFromFragment(android.app.Fragment, android.content.Intent, int, android.os.Bundle);
+ method public boolean onUseFragmentManagerInflaterFactory();
+ }
+
public abstract class FragmentManager {
ctor public FragmentManager();
method public abstract void addOnBackStackChangedListener(android.app.FragmentManager.OnBackStackChangedListener);
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 69cba78..e79e20c 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -108,6 +108,7 @@
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
/**
* An activity is a single, focused thing that the user can do. Almost all
@@ -706,8 +707,6 @@
/*package*/ ActivityThread mMainThread;
Activity mParent;
boolean mCalled;
- boolean mCheckedForLoaderManager;
- boolean mLoadersStarted;
/*package*/ boolean mResumed;
private boolean mStopped;
boolean mFinished;
@@ -726,8 +725,8 @@
static final class NonConfigurationInstances {
Object activity;
HashMap<String, Object> children;
- ArrayList<Fragment> fragments;
- ArrayMap<String, LoaderManagerImpl> loaders;
+ List<Fragment> fragments;
+ ArrayMap<String, LoaderManager> loaders;
VoiceInteractor voiceInteractor;
}
/* package */ NonConfigurationInstances mLastNonConfigurationInstances;
@@ -747,26 +746,13 @@
private CharSequence mTitle;
private int mTitleColor = 0;
- final FragmentManagerImpl mFragments = new FragmentManagerImpl();
- final FragmentContainer mContainer = new FragmentContainer() {
- @Override
- @Nullable
- public View findViewById(int id) {
- return Activity.this.findViewById(id);
- }
- @Override
- public boolean hasView() {
- Window window = Activity.this.getWindow();
- return (window != null && window.peekDecorView() != null);
- }
- };
+ // we must have a handler before the FragmentController is constructed
+ final Handler mHandler = new Handler();
+ final FragmentController mFragments = FragmentController.createController(new HostCallbacks());
// Most recent call to requestVisibleBehind().
boolean mVisibleBehind;
- ArrayMap<String, LoaderManagerImpl> mAllLoaderManagers;
- LoaderManagerImpl mLoaderManager;
-
private static final class ManagedCursor {
ManagedCursor(Cursor cursor) {
mCursor = cursor;
@@ -802,7 +788,6 @@
private final Object mInstanceTracker = StrictMode.trackActivity(this);
private Thread mUiThread;
- final Handler mHandler = new Handler();
ActivityTransitionState mActivityTransitionState = new ActivityTransitionState();
SharedElementCallback mEnterTransitionListener = SharedElementCallback.NULL_CALLBACK;
@@ -863,28 +848,7 @@
* Return the LoaderManager for this activity, creating it if needed.
*/
public LoaderManager getLoaderManager() {
- if (mLoaderManager != null) {
- return mLoaderManager;
- }
- mCheckedForLoaderManager = true;
- mLoaderManager = getLoaderManager("(root)", mLoadersStarted, true);
- return mLoaderManager;
- }
-
- LoaderManagerImpl getLoaderManager(String who, boolean started, boolean create) {
- if (mAllLoaderManagers == null) {
- mAllLoaderManagers = new ArrayMap<String, LoaderManagerImpl>();
- }
- LoaderManagerImpl lm = mAllLoaderManagers.get(who);
- if (lm == null) {
- if (create) {
- lm = new LoaderManagerImpl(who, this, started);
- mAllLoaderManagers.put(who, lm);
- }
- } else {
- lm.updateActivity(this);
- }
- return lm;
+ return mFragments.getLoaderManager();
}
/**
@@ -931,7 +895,7 @@
protected void onCreate(@Nullable Bundle savedInstanceState) {
if (DEBUG_LIFECYCLE) Slog.v(TAG, "onCreate " + this + ": " + savedInstanceState);
if (mLastNonConfigurationInstances != null) {
- mAllLoaderManagers = mLastNonConfigurationInstances.loaders;
+ mFragments.restoreLoaderNonConfig(mLastNonConfigurationInstances.loaders);
}
if (mActivityInfo.parentActivityName != null) {
if (mActionBar == null) {
@@ -1172,15 +1136,7 @@
if (DEBUG_LIFECYCLE) Slog.v(TAG, "onStart " + this);
mCalled = true;
- if (!mLoadersStarted) {
- mLoadersStarted = true;
- if (mLoaderManager != null) {
- mLoaderManager.doStart();
- } else if (!mCheckedForLoaderManager) {
- mLoaderManager = getLoaderManager("(root)", mLoadersStarted, false);
- }
- mCheckedForLoaderManager = true;
- }
+ mFragments.doLoaderStart();
getApplication().dispatchActivityStarted(this);
}
@@ -1873,27 +1829,9 @@
NonConfigurationInstances retainNonConfigurationInstances() {
Object activity = onRetainNonConfigurationInstance();
HashMap<String, Object> children = onRetainNonConfigurationChildInstances();
- ArrayList<Fragment> fragments = mFragments.retainNonConfig();
- boolean retainLoaders = false;
- if (mAllLoaderManagers != null) {
- // prune out any loader managers that were already stopped and so
- // have nothing useful to retain.
- final int N = mAllLoaderManagers.size();
- LoaderManagerImpl loaders[] = new LoaderManagerImpl[N];
- for (int i=N-1; i>=0; i--) {
- loaders[i] = mAllLoaderManagers.valueAt(i);
- }
- for (int i=0; i<N; i++) {
- LoaderManagerImpl lm = loaders[i];
- if (lm.mRetaining) {
- retainLoaders = true;
- } else {
- lm.doDestroy();
- mAllLoaderManagers.remove(lm.mWho);
- }
- }
- }
- if (activity == null && children == null && fragments == null && !retainLoaders
+ List<Fragment> fragments = mFragments.retainNonConfig();
+ ArrayMap<String, LoaderManager> loaders = mFragments.retainLoaderNonConfig();
+ if (activity == null && children == null && fragments == null && loaders == null
&& mVoiceInteractor == null) {
return null;
}
@@ -1902,7 +1840,7 @@
nci.activity = activity;
nci.children = children;
nci.fragments = fragments;
- nci.loaders = mAllLoaderManagers;
+ nci.loaders = loaders;
nci.voiceInteractor = mVoiceInteractor;
return nci;
}
@@ -1924,18 +1862,7 @@
* with this activity.
*/
public FragmentManager getFragmentManager() {
- return mFragments;
- }
-
- void invalidateFragment(String who) {
- //Log.v(TAG, "invalidateFragmentIndex: index=" + index);
- if (mAllLoaderManagers != null) {
- LoaderManagerImpl lm = mAllLoaderManagers.get(who);
- if (lm != null && !lm.mRetaining) {
- lm.doDestroy();
- mAllLoaderManagers.remove(who);
- }
- }
+ return mFragments.getFragmentManager();
}
/**
@@ -2518,7 +2445,7 @@
return;
}
- if (!mFragments.popBackStackImmediate()) {
+ if (!mFragments.getFragmentManager().popBackStackImmediate()) {
finishAfterTransition();
}
}
@@ -5518,21 +5445,13 @@
writer.print(mResumed); writer.print(" mStopped=");
writer.print(mStopped); writer.print(" mFinished=");
writer.println(mFinished);
- writer.print(innerPrefix); writer.print("mLoadersStarted=");
- writer.println(mLoadersStarted);
writer.print(innerPrefix); writer.print("mChangingConfigurations=");
writer.println(mChangingConfigurations);
writer.print(innerPrefix); writer.print("mCurrentConfig=");
writer.println(mCurrentConfig);
- if (mLoaderManager != null) {
- writer.print(prefix); writer.print("Loader Manager ");
- writer.print(Integer.toHexString(System.identityHashCode(mLoaderManager)));
- writer.println(":");
- mLoaderManager.dump(prefix + " ", fd, writer, args);
- }
-
- mFragments.dump(prefix, fd, writer, args);
+ mFragments.dumpLoaders(innerPrefix, fd, writer, args);
+ mFragments.getFragmentManager().dump(innerPrefix, fd, writer, args);
if (getWindow() != null &&
getWindow().peekDecorView() != null &&
@@ -6128,7 +6047,7 @@
Configuration config, String referrer, IVoiceInteractor voiceInteractor) {
attachBaseContext(context);
- mFragments.attachActivity(this, mContainer, null);
+ mFragments.attachHost(null /*parent*/);
mWindow = new PhoneWindow(this);
mWindow.setCallback(this);
@@ -6211,18 +6130,7 @@
" did not call through to super.onStart()");
}
mFragments.dispatchStart();
- if (mAllLoaderManagers != null) {
- final int N = mAllLoaderManagers.size();
- LoaderManagerImpl loaders[] = new LoaderManagerImpl[N];
- for (int i=N-1; i>=0; i--) {
- loaders[i] = mAllLoaderManagers.valueAt(i);
- }
- for (int i=0; i<N; i++) {
- LoaderManagerImpl lm = loaders[i];
- lm.finishRetain();
- lm.doReportStart();
- }
- }
+ mFragments.reportLoaderStart();
mActivityTransitionState.enterReady(this);
}
@@ -6328,16 +6236,7 @@
final void performStop() {
mDoReportFullyDrawn = false;
- if (mLoadersStarted) {
- mLoadersStarted = false;
- if (mLoaderManager != null) {
- if (!mChangingConfigurations) {
- mLoaderManager.doStop();
- } else {
- mLoaderManager.doRetain();
- }
- }
- }
+ mFragments.doLoaderStop(mChangingConfigurations /*retain*/);
if (!mStopped) {
if (mWindow != null) {
@@ -6379,9 +6278,7 @@
mWindow.destroy();
mFragments.dispatchDestroy();
onDestroy();
- if (mLoaderManager != null) {
- mLoaderManager.doDestroy();
- }
+ mFragments.doLoaderDestroy();
if (mVoiceInteractor != null) {
mVoiceInteractor.detachActivity();
}
@@ -6541,4 +6438,74 @@
return intent != null
&& PackageManager.ACTION_REQUEST_PERMISSIONS.equals(intent.getAction());
}
+
+ class HostCallbacks extends FragmentHostCallback<Activity> {
+ public HostCallbacks() {
+ super(Activity.this /*activity*/);
+ }
+
+ @Override
+ public void onDump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
+ Activity.this.dump(prefix, fd, writer, args);
+ }
+
+ @Override
+ public boolean onShouldSaveFragmentState(Fragment fragment) {
+ return !isFinishing();
+ }
+
+ @Override
+ public LayoutInflater onGetLayoutInflater() {
+ final LayoutInflater result = Activity.this.getLayoutInflater();
+ if (onUseFragmentManagerInflaterFactory()) {
+ return result.cloneInContext(Activity.this);
+ }
+ return result;
+ }
+
+ @Override
+ public boolean onUseFragmentManagerInflaterFactory() {
+ // Newer platform versions use the child fragment manager's LayoutInflaterFactory.
+ return getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP;
+ }
+
+ @Override
+ public Activity onGetHost() {
+ return Activity.this;
+ }
+
+ @Override
+ public void onInvalidateOptionsMenu() {
+ Activity.this.invalidateOptionsMenu();
+ }
+
+ @Override
+ public void onStartActivityFromFragment(Fragment fragment, Intent intent, int requestCode,
+ Bundle options) {
+ Activity.this.startActivityFromFragment(fragment, intent, requestCode, options);
+ }
+
+ @Override
+ public boolean onHasWindowAnimations() {
+ return getWindow() != null;
+ }
+
+ @Override
+ public int onGetWindowAnimations() {
+ final Window w = getWindow();
+ return (w == null) ? 0 : w.getAttributes().windowAnimations;
+ }
+
+ @Nullable
+ @Override
+ public View onFindViewById(int id) {
+ return Activity.this.findViewById(id);
+ }
+
+ @Override
+ public boolean onHasView() {
+ final Window w = getWindow();
+ return (w != null && w.peekDecorView() != null);
+ }
+ }
}
diff --git a/core/java/android/app/BackStackRecord.java b/core/java/android/app/BackStackRecord.java
index 8fb048b..49644a7 100644
--- a/core/java/android/app/BackStackRecord.java
+++ b/core/java/android/app/BackStackRecord.java
@@ -416,14 +416,14 @@
public CharSequence getBreadCrumbTitle() {
if (mBreadCrumbTitleRes != 0) {
- return mManager.mActivity.getText(mBreadCrumbTitleRes);
+ return mManager.mHost.getContext().getText(mBreadCrumbTitleRes);
}
return mBreadCrumbTitleText;
}
public CharSequence getBreadCrumbShortTitle() {
if (mBreadCrumbShortTitleRes != 0) {
- return mManager.mActivity.getText(mBreadCrumbShortTitleRes);
+ return mManager.mHost.getContext().getText(mBreadCrumbShortTitleRes);
}
return mBreadCrumbShortTitleText;
}
@@ -868,7 +868,7 @@
*/
private void calculateFragments(SparseArray<Fragment> firstOutFragments,
SparseArray<Fragment> lastInFragments) {
- if (!mManager.mContainer.hasView()) {
+ if (!mManager.mContainer.onHasView()) {
return; // nothing to see, so no transitions
}
Op op = mHead;
@@ -926,7 +926,7 @@
*/
public void calculateBackFragments(SparseArray<Fragment> firstOutFragments,
SparseArray<Fragment> lastInFragments) {
- if (!mManager.mContainer.hasView()) {
+ if (!mManager.mContainer.onHasView()) {
return; // nothing to see, so no transitions
}
Op op = mHead;
@@ -1002,7 +1002,7 @@
// Adding a non-existent target view makes sure that the transitions don't target
// any views by default. They'll only target the views we tell add. If we don't
// add any, then no views will be targeted.
- state.nonExistentView = new View(mManager.mActivity);
+ state.nonExistentView = new View(mManager.mHost.getContext());
// Go over all leaving fragments.
for (int i = 0; i < firstOutFragments.size(); i++) {
@@ -1275,7 +1275,7 @@
*/
private void configureTransitions(int containerId, TransitionState state, boolean isBack,
SparseArray<Fragment> firstOutFragments, SparseArray<Fragment> lastInFragments) {
- ViewGroup sceneRoot = (ViewGroup) mManager.mContainer.findViewById(containerId);
+ ViewGroup sceneRoot = (ViewGroup) mManager.mContainer.onFindViewById(containerId);
if (sceneRoot != null) {
Fragment inFragment = lastInFragments.get(containerId);
Fragment outFragment = firstOutFragments.get(containerId);
diff --git a/core/java/android/app/DialogFragment.java b/core/java/android/app/DialogFragment.java
index bde5a61..2fb8cc2 100644
--- a/core/java/android/app/DialogFragment.java
+++ b/core/java/android/app/DialogFragment.java
@@ -410,7 +410,7 @@
return (LayoutInflater)mDialog.getContext().getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
}
- return (LayoutInflater)mActivity.getSystemService(
+ return (LayoutInflater) mHost.getContext().getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
}
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index 4fdae7f..91d810e 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -26,7 +26,6 @@
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
-import android.os.Build;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -94,19 +93,20 @@
mSavedFragmentState = in.readBundle();
}
- public Fragment instantiate(Activity activity, Fragment parent) {
+ public Fragment instantiate(FragmentHostCallback host, Fragment parent) {
if (mInstance != null) {
return mInstance;
}
+ final Context context = host.getContext();
if (mArguments != null) {
- mArguments.setClassLoader(activity.getClassLoader());
+ mArguments.setClassLoader(context.getClassLoader());
}
- mInstance = Fragment.instantiate(activity, mClassName, mArguments);
+ mInstance = Fragment.instantiate(context, mClassName, mArguments);
if (mSavedFragmentState != null) {
- mSavedFragmentState.setClassLoader(activity.getClassLoader());
+ mSavedFragmentState.setClassLoader(context.getClassLoader());
mInstance.mSavedFragmentState = mSavedFragmentState;
}
mInstance.setIndex(mIndex, parent);
@@ -117,7 +117,7 @@
mInstance.mTag = mTag;
mInstance.mRetainInstance = mRetainInstance;
mInstance.mDetached = mDetached;
- mInstance.mFragmentManager = activity.mFragments;
+ mInstance.mFragmentManager = host.mFragmentManager;
if (FragmentManagerImpl.DEBUG) Log.v(FragmentManagerImpl.TAG,
"Instantiated fragment " + mInstance);
@@ -425,7 +425,7 @@
FragmentManagerImpl mFragmentManager;
// Activity this fragment is attached to.
- Activity mActivity;
+ FragmentHostCallback mHost;
// Private fragment manager for child fragments inside of this one.
FragmentManagerImpl mChildFragmentManager;
@@ -775,20 +775,36 @@
}
/**
+ * Return the {@link Context} this fragment is currently associated with.
+ */
+ public Context getContext() {
+ return mHost == null ? null : mHost.getContext();
+ }
+
+ /**
* Return the Activity this fragment is currently associated with.
*/
final public Activity getActivity() {
- return mActivity;
+ return mHost == null ? null : mHost.getActivity();
+ }
+
+ /**
+ * Return the host object of this fragment. May return {@code null} if the fragment
+ * isn't currently being hosted.
+ */
+ @Nullable
+ final public Object getHost() {
+ return mHost == null ? null : mHost.onGetHost();
}
/**
* Return <code>getActivity().getResources()</code>.
*/
final public Resources getResources() {
- if (mActivity == null) {
+ if (mHost == null) {
throw new IllegalStateException("Fragment " + this + " not attached to Activity");
}
- return mActivity.getResources();
+ return mHost.getContext().getResources();
}
/**
@@ -870,7 +886,7 @@
* Return true if the fragment is currently added to its activity.
*/
final public boolean isAdded() {
- return mActivity != null && mAdded;
+ return mHost != null && mAdded;
}
/**
@@ -1037,11 +1053,11 @@
if (mLoaderManager != null) {
return mLoaderManager;
}
- if (mActivity == null) {
+ if (mHost == null) {
throw new IllegalStateException("Fragment " + this + " not attached to Activity");
}
mCheckedForLoaderManager = true;
- mLoaderManager = mActivity.getLoaderManager(mWho, mLoadersStarted, true);
+ mLoaderManager = mHost.getLoaderManager(mWho, mLoadersStarted, true);
return mLoaderManager;
}
@@ -1065,15 +1081,15 @@
* Context.startActivity(Intent, Bundle)} for more details.
*/
public void startActivity(Intent intent, Bundle options) {
- if (mActivity == null) {
+ if (mHost == null) {
throw new IllegalStateException("Fragment " + this + " not attached to Activity");
}
if (options != null) {
- mActivity.startActivityFromFragment(this, intent, -1, options);
+ mHost.onStartActivityFromFragment(this, intent, -1, options);
} else {
// Note we want to go through this call for compatibility with
// applications that may have overridden the method.
- mActivity.startActivityFromFragment(this, intent, -1);
+ mHost.onStartActivityFromFragment(this, intent, -1, null /*options*/);
}
}
@@ -1090,10 +1106,10 @@
* containing Activity.
*/
public void startActivityForResult(Intent intent, int requestCode, Bundle options) {
- if (mActivity == null) {
+ if (mHost == null) {
throw new IllegalStateException("Fragment " + this + " not attached to Activity");
}
- mActivity.startActivityFromFragment(this, intent, requestCode, options);
+ mHost.onStartActivityFromFragment(this, intent, requestCode, options);
}
/**
@@ -1181,11 +1197,12 @@
* @see android.content.Context#checkSelfPermission(String)
*/
public final void requestPermissions(@NonNull String[] permissions, int requestCode) {
- if (mActivity == null) {
+ if (mHost == null) {
throw new IllegalStateException("Fragment " + this + " not attached to Activity");
}
- Intent intent = mActivity.getPackageManager().buildRequestPermissionsIntent(permissions);
- mActivity.startActivityFromFragment(this, intent, requestCode, null);
+ Intent intent =
+ mHost.getContext().getPackageManager().buildRequestPermissionsIntent(permissions);
+ mHost.onStartActivityFromFragment(this, intent, requestCode, null);
}
/**
@@ -1211,19 +1228,16 @@
* inflation. Maybe this should become a public API. Note sure.
*/
public LayoutInflater getLayoutInflater(Bundle savedInstanceState) {
- // Newer platform versions use the child fragment manager's LayoutInflaterFactory.
- if (mActivity.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP) {
- LayoutInflater result = mActivity.getLayoutInflater().cloneInContext(mActivity);
+ final LayoutInflater result = mHost.onGetLayoutInflater();
+ if (mHost.onUseFragmentManagerInflaterFactory()) {
getChildFragmentManager(); // Init if needed; use raw implementation below.
result.setPrivateFactory(mChildFragmentManager.getLayoutInflaterFactory());
- return result;
- } else {
- return mActivity.getLayoutInflater();
}
+ return result;
}
/**
- * @deprecated Use {@link #onInflate(Activity, AttributeSet, Bundle)} instead.
+ * @deprecated Use {@link #onInflate(Context, AttributeSet, Bundle)} instead.
*/
@Deprecated
public void onInflate(AttributeSet attrs, Bundle savedInstanceState) {
@@ -1266,29 +1280,29 @@
* {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentArguments.java
* create}
*
- * @param activity The Activity that is inflating this fragment.
+ * @param context The Context that is inflating this fragment.
* @param attrs The attributes at the tag where the fragment is
* being created.
* @param savedInstanceState If the fragment is being re-created from
* a previous saved state, this is the state.
*/
- public void onInflate(Activity activity, AttributeSet attrs, Bundle savedInstanceState) {
+ public void onInflate(Context context, AttributeSet attrs, Bundle savedInstanceState) {
onInflate(attrs, savedInstanceState);
mCalled = true;
- TypedArray a = activity.obtainStyledAttributes(attrs,
+ TypedArray a = context.obtainStyledAttributes(attrs,
com.android.internal.R.styleable.Fragment);
- mEnterTransition = loadTransition(activity, a, mEnterTransition, null,
+ mEnterTransition = loadTransition(context, a, mEnterTransition, null,
com.android.internal.R.styleable.Fragment_fragmentEnterTransition);
- mReturnTransition = loadTransition(activity, a, mReturnTransition, USE_DEFAULT_TRANSITION,
+ mReturnTransition = loadTransition(context, a, mReturnTransition, USE_DEFAULT_TRANSITION,
com.android.internal.R.styleable.Fragment_fragmentReturnTransition);
- mExitTransition = loadTransition(activity, a, mExitTransition, null,
+ mExitTransition = loadTransition(context, a, mExitTransition, null,
com.android.internal.R.styleable.Fragment_fragmentExitTransition);
- mReenterTransition = loadTransition(activity, a, mReenterTransition, USE_DEFAULT_TRANSITION,
+ mReenterTransition = loadTransition(context, a, mReenterTransition, USE_DEFAULT_TRANSITION,
com.android.internal.R.styleable.Fragment_fragmentReenterTransition);
- mSharedElementEnterTransition = loadTransition(activity, a, mSharedElementEnterTransition,
+ mSharedElementEnterTransition = loadTransition(context, a, mSharedElementEnterTransition,
null, com.android.internal.R.styleable.Fragment_fragmentSharedElementEnterTransition);
- mSharedElementReturnTransition = loadTransition(activity, a, mSharedElementReturnTransition,
+ mSharedElementReturnTransition = loadTransition(context, a, mSharedElementReturnTransition,
USE_DEFAULT_TRANSITION,
com.android.internal.R.styleable.Fragment_fragmentSharedElementReturnTransition);
if (mAllowEnterTransitionOverlap == null) {
@@ -1303,9 +1317,30 @@
}
/**
- * Called when a fragment is first attached to its activity.
+ * @deprecated Use {@link #onInflate(Context, AttributeSet, Bundle)} instead.
+ */
+ @Deprecated
+ public void onInflate(Activity activity, AttributeSet attrs, Bundle savedInstanceState) {
+ mCalled = true;
+ }
+
+ /**
+ * Called when a fragment is first attached to its context.
* {@link #onCreate(Bundle)} will be called after this.
*/
+ public void onAttach(Context context) {
+ mCalled = true;
+ final Activity hostActivity = mHost == null ? null : mHost.getActivity();
+ if (hostActivity != null) {
+ mCalled = false;
+ onAttach(hostActivity);
+ }
+ }
+
+ /**
+ * @deprecated Use {@link #onAttach(Context)} instead.
+ */
+ @Deprecated
public void onAttach(Activity activity) {
mCalled = true;
}
@@ -1428,7 +1463,7 @@
mLoadersStarted = true;
if (!mCheckedForLoaderManager) {
mCheckedForLoaderManager = true;
- mLoaderManager = mActivity.getLoaderManager(mWho, mLoadersStarted, false);
+ mLoaderManager = mHost.getLoaderManager(mWho, mLoadersStarted, false);
}
if (mLoaderManager != null) {
mLoaderManager.doStart();
@@ -1521,7 +1556,7 @@
// + " mLoaderManager=" + mLoaderManager);
if (!mCheckedForLoaderManager) {
mCheckedForLoaderManager = true;
- mLoaderManager = mActivity.getLoaderManager(mWho, mLoadersStarted, false);
+ mLoaderManager = mHost.getLoaderManager(mWho, mLoadersStarted, false);
}
if (mLoaderManager != null) {
mLoaderManager.doDestroy();
@@ -1546,7 +1581,7 @@
mBackStackNesting = 0;
mFragmentManager = null;
mChildFragmentManager = null;
- mActivity = null;
+ mHost = null;
mFragmentId = 0;
mContainerId = 0;
mTag = null;
@@ -2034,9 +2069,9 @@
writer.print(prefix); writer.print("mFragmentManager=");
writer.println(mFragmentManager);
}
- if (mActivity != null) {
- writer.print(prefix); writer.print("mActivity=");
- writer.println(mActivity);
+ if (mHost != null) {
+ writer.print(prefix); writer.print("mHost=");
+ writer.println(mHost);
}
if (mParentFragment != null) {
writer.print(prefix); writer.print("mParentFragment=");
@@ -2094,10 +2129,10 @@
void instantiateChildFragmentManager() {
mChildFragmentManager = new FragmentManagerImpl();
- mChildFragmentManager.attachActivity(mActivity, new FragmentContainer() {
+ mChildFragmentManager.attachController(mHost, new FragmentContainer() {
@Override
@Nullable
- public View findViewById(int id) {
+ public View onFindViewById(int id) {
if (mView == null) {
throw new IllegalStateException("Fragment does not have a view");
}
@@ -2105,7 +2140,7 @@
}
@Override
- public boolean hasView() {
+ public boolean onHasView() {
return (mView != null);
}
}, this);
@@ -2319,13 +2354,13 @@
mLoadersStarted = false;
if (!mCheckedForLoaderManager) {
mCheckedForLoaderManager = true;
- mLoaderManager = mActivity.getLoaderManager(mWho, mLoadersStarted, false);
+ mLoaderManager = mHost.getLoaderManager(mWho, mLoadersStarted, false);
}
if (mLoaderManager != null) {
- if (mActivity == null || !mActivity.mChangingConfigurations) {
- mLoaderManager.doStop();
- } else {
+ if (mRetaining) {
mLoaderManager.doRetain();
+ } else {
+ mLoaderManager.doStop();
}
}
}
diff --git a/core/java/android/app/FragmentContainer.java b/core/java/android/app/FragmentContainer.java
new file mode 100644
index 0000000..b2e0300
--- /dev/null
+++ b/core/java/android/app/FragmentContainer.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2015 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 android.app;
+
+import android.annotation.IdRes;
+import android.annotation.Nullable;
+import android.view.View;
+
+/**
+ * Callbacks to a {@link Fragment}'s container.
+ */
+public abstract class FragmentContainer {
+ /**
+ * Return the view with the given resource ID. May return {@code null} if the
+ * view is not a child of this container.
+ */
+ @Nullable
+ public abstract View onFindViewById(@IdRes int id);
+
+ /**
+ * Return {@code true} if the container holds any view.
+ */
+ public abstract boolean onHasView();
+}
diff --git a/core/java/android/app/FragmentController.java b/core/java/android/app/FragmentController.java
new file mode 100644
index 0000000..28dadfa
--- /dev/null
+++ b/core/java/android/app/FragmentController.java
@@ -0,0 +1,384 @@
+/*
+ * Copyright (C) 2015 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 android.app;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.util.ArrayMap;
+import android.util.AttributeSet;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.List;
+
+/**
+ * Provides integration points with a {@link FragmentManager} for a fragment host.
+ * <p>
+ * It is the responsibility of the host to take care of the Fragment's lifecycle.
+ * The methods provided by {@link FragmentController} are for that purpose.
+ */
+public class FragmentController {
+ private final FragmentHostCallback<?> mHost;
+
+ /**
+ * Returns a {@link FragmentController}.
+ */
+ public static final FragmentController createController(FragmentHostCallback<?> callbacks) {
+ return new FragmentController(callbacks);
+ }
+
+ private FragmentController(FragmentHostCallback<?> callbacks) {
+ mHost = callbacks;
+ }
+
+ /**
+ * Returns a {@link FragmentManager} for this controller.
+ */
+ public FragmentManager getFragmentManager() {
+ return mHost.getFragmentManagerImpl();
+ }
+
+ /**
+ * Returns a {@link LoaderManager}.
+ */
+ public LoaderManager getLoaderManager() {
+ return mHost.getLoaderManagerImpl();
+ }
+
+ /**
+ * Returns a fragment with the given identifier.
+ */
+ @Nullable
+ public Fragment findFragmentByWho(String who) {
+ return mHost.mFragmentManager.findFragmentByWho(who);
+ }
+
+ /**
+ * Attaches the host to the FragmentManager for this controller. The host must be
+ * attached before the FragmentManager can be used to manage Fragments.
+ * */
+ public void attachHost(Fragment parent) {
+ mHost.mFragmentManager.attachController(
+ mHost, mHost /*container*/, parent);
+ }
+
+ /**
+ * Instantiates a Fragment's view.
+ *
+ * @param parent The parent that the created view will be placed
+ * in; <em>note that this may be null</em>.
+ * @param name Tag name to be inflated.
+ * @param context The context the view is being created in.
+ * @param attrs Inflation attributes as specified in XML file.
+ *
+ * @return view the newly created view
+ */
+ public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
+ return mHost.mFragmentManager.onCreateView(parent, name, context, attrs);
+ }
+
+ /**
+ * Marks the fragment state as unsaved. This allows for "state loss" detection.
+ */
+ public void noteStateNotSaved() {
+ mHost.mFragmentManager.noteStateNotSaved();
+ }
+
+ /**
+ * Saves the state for all Fragments.
+ */
+ public Parcelable saveAllState() {
+ return mHost.mFragmentManager.saveAllState();
+ }
+
+ /**
+ * Restores the saved state for all Fragments. The given Fragment list are Fragment
+ * instances retained across configuration changes.
+ *
+ * @see #retainNonConfig()
+ */
+ public void restoreAllState(Parcelable state, List<Fragment> nonConfigList) {
+ mHost.mFragmentManager.restoreAllState(state, nonConfigList);
+ }
+
+ /**
+ * Returns a list of Fragments that have opted to retain their instance across
+ * configuration changes.
+ */
+ public List<Fragment> retainNonConfig() {
+ return mHost.mFragmentManager.retainNonConfig();
+ }
+
+ /**
+ * Moves all Fragments managed by the controller's FragmentManager
+ * into the create state.
+ * <p>Call when Fragments should be created.
+ *
+ * @see Fragment#onCreate(Bundle)
+ */
+ public void dispatchCreate() {
+ mHost.mFragmentManager.dispatchCreate();
+ }
+
+ /**
+ * Moves all Fragments managed by the controller's FragmentManager
+ * into the activity created state.
+ * <p>Call when Fragments should be informed their host has been created.
+ *
+ * @see Fragment#onActivityCreated(Bundle)
+ */
+ public void dispatchActivityCreated() {
+ mHost.mFragmentManager.dispatchActivityCreated();
+ }
+
+ /**
+ * Moves all Fragments managed by the controller's FragmentManager
+ * into the start state.
+ * <p>Call when Fragments should be started.
+ *
+ * @see Fragment#onStart()
+ */
+ public void dispatchStart() {
+ mHost.mFragmentManager.dispatchStart();
+ }
+
+ /**
+ * Moves all Fragments managed by the controller's FragmentManager
+ * into the resume state.
+ * <p>Call when Fragments should be resumed.
+ *
+ * @see Fragment#onResume()
+ */
+ public void dispatchResume() {
+ mHost.mFragmentManager.dispatchResume();
+ }
+
+ /**
+ * Moves all Fragments managed by the controller's FragmentManager
+ * into the pause state.
+ * <p>Call when Fragments should be paused.
+ *
+ * @see Fragment#onPause()
+ */
+ public void dispatchPause() {
+ mHost.mFragmentManager.dispatchPause();
+ }
+
+ /**
+ * Moves all Fragments managed by the controller's FragmentManager
+ * into the stop state.
+ * <p>Call when Fragments should be stopped.
+ *
+ * @see Fragment#onStop()
+ */
+ public void dispatchStop() {
+ mHost.mFragmentManager.dispatchStop();
+ }
+
+ /**
+ * Moves all Fragments managed by the controller's FragmentManager
+ * into the destroy view state.
+ * <p>Call when the Fragment's views should be destroyed.
+ *
+ * @see Fragment#onDestroyView()
+ */
+ public void dispatchDestroyView() {
+ mHost.mFragmentManager.dispatchDestroyView();
+ }
+
+ /**
+ * Moves all Fragments managed by the controller's FragmentManager
+ * into the destroy state.
+ * <p>Call when Fragments should be destroyed.
+ *
+ * @see Fragment#onDestroy()
+ */
+ public void dispatchDestroy() {
+ mHost.mFragmentManager.dispatchDestroy();
+ }
+
+ /**
+ * Lets all Fragments managed by the controller's FragmentManager
+ * know a configuration change occurred.
+ * <p>Call when there is a configuration change.
+ *
+ * @see Fragment#onConfigurationChanged(Configuration)
+ */
+ public void dispatchConfigurationChanged(Configuration newConfig) {
+ mHost.mFragmentManager.dispatchConfigurationChanged(newConfig);
+ }
+
+ /**
+ * Lets all Fragments managed by the controller's FragmentManager
+ * know the device is in a low memory condition.
+ * <p>Call when the device is low on memory and Fragment's should trim
+ * their memory usage.
+ *
+ * @see Fragment#onLowMemory()
+ */
+ public void dispatchLowMemory() {
+ mHost.mFragmentManager.dispatchLowMemory();
+ }
+
+ /**
+ * Lets all Fragments managed by the controller's FragmentManager
+ * know they should trim their memory usage.
+ * <p>Call when the Fragment can release allocated memory [such as if
+ * the Fragment is in the background].
+ *
+ * @see Fragment#onTrimMemory(int)
+ */
+ public void dispatchTrimMemory(int level) {
+ mHost.mFragmentManager.dispatchTrimMemory(level);
+ }
+
+ /**
+ * Lets all Fragments managed by the controller's FragmentManager
+ * know they should create an options menu.
+ * <p>Call when the Fragment should create an options menu.
+ *
+ * @return {@code true} if the options menu contains items to display
+ * @see Fragment#onCreateOptionsMenu(Menu, MenuInflater)
+ */
+ public boolean dispatchCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ return mHost.mFragmentManager.dispatchCreateOptionsMenu(menu, inflater);
+ }
+
+ /**
+ * Lets all Fragments managed by the controller's FragmentManager
+ * know they should prepare their options menu for display.
+ * <p>Call immediately before displaying the Fragment's options menu.
+ *
+ * @return {@code true} if the options menu contains items to display
+ * @see Fragment#onPrepareOptionsMenu(Menu)
+ */
+ public boolean dispatchPrepareOptionsMenu(Menu menu) {
+ return mHost.mFragmentManager.dispatchPrepareOptionsMenu(menu);
+ }
+
+ /**
+ * Sends an option item selection event to the Fragments managed by the
+ * controller's FragmentManager. Once the event has been consumed,
+ * no additional handling will be performed.
+ * <p>Call immediately after an options menu item has been selected
+ *
+ * @return {@code true} if the options menu selection event was consumed
+ * @see Fragment#onOptionsItemSelected(MenuItem)
+ */
+ public boolean dispatchOptionsItemSelected(MenuItem item) {
+ return mHost.mFragmentManager.dispatchOptionsItemSelected(item);
+ }
+
+ /**
+ * Sends a context item selection event to the Fragments managed by the
+ * controller's FragmentManager. Once the event has been consumed,
+ * no additional handling will be performed.
+ * <p>Call immediately after an options menu item has been selected
+ *
+ * @return {@code true} if the context menu selection event was consumed
+ * @see Fragment#onContextItemSelected(MenuItem)
+ */
+ public boolean dispatchContextItemSelected(MenuItem item) {
+ return mHost.mFragmentManager.dispatchContextItemSelected(item);
+ }
+
+ /**
+ * Lets all Fragments managed by the controller's FragmentManager
+ * know their options menu has closed.
+ * <p>Call immediately after closing the Fragment's options menu.
+ *
+ * @see Fragment#onOptionsMenuClosed(Menu)
+ */
+ public void dispatchOptionsMenuClosed(Menu menu) {
+ mHost.mFragmentManager.dispatchOptionsMenuClosed(menu);
+ }
+
+ /**
+ * Execute any pending actions for the Fragments managed by the
+ * controller's FragmentManager.
+ * <p>Call when queued actions can be performed [eg when the
+ * Fragment moves into a start or resume state].
+ * @return {@code true} if queued actions were performed
+ */
+ public boolean execPendingActions() {
+ return mHost.mFragmentManager.execPendingActions();
+ }
+
+ /**
+ * Starts the loaders.
+ */
+ public void doLoaderStart() {
+ mHost.doLoaderStart();
+ }
+
+ /**
+ * Stops the loaders, optionally retaining their state. This is useful for keeping the
+ * loader state across configuration changes.
+ *
+ * @param retain When {@code true}, the loaders aren't stopped, but, their instances
+ * are retained in a started state
+ */
+ public void doLoaderStop(boolean retain) {
+ mHost.doLoaderStop(retain);
+ }
+
+ /**
+ * Destroys the loaders and, if their state is not being retained, removes them.
+ */
+ public void doLoaderDestroy() {
+ mHost.doLoaderDestroy();
+ }
+
+ /**
+ * Lets the loaders know the host is ready to receive notifications.
+ */
+ public void reportLoaderStart() {
+ mHost.reportLoaderStart();
+ }
+
+ /**
+ * Returns a list of LoaderManagers that have opted to retain their instance across
+ * configuration changes.
+ */
+ public ArrayMap<String, LoaderManager> retainLoaderNonConfig() {
+ return mHost.retainLoaderNonConfig();
+ }
+
+ /**
+ * Restores the saved state for all LoaderManagers. The given LoaderManager list are
+ * LoaderManager instances retained across configuration changes.
+ *
+ * @see #retainLoaderNonConfig()
+ */
+ public void restoreLoaderNonConfig(ArrayMap<String, LoaderManager> loaderManagers) {
+ mHost.restoreLoaderNonConfig(loaderManagers);
+ }
+
+ /**
+ * Dumps the current state of the loaders.
+ */
+ public void dumpLoaders(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
+ mHost.dumpLoaders(prefix, fd, writer, args);
+ }
+}
diff --git a/core/java/android/app/FragmentHostCallback.java b/core/java/android/app/FragmentHostCallback.java
new file mode 100644
index 0000000..dad2c79
--- /dev/null
+++ b/core/java/android/app/FragmentHostCallback.java
@@ -0,0 +1,315 @@
+/*
+ * Copyright (C) 2015 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 android.app;
+
+import android.annotation.Nullable;
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.util.ArrayMap;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+/**
+ * Integration points with the Fragment host.
+ * <p>
+ * Fragments may be hosted by any object; such as an {@link Activity}. In order to
+ * host fragments, implement {@link FragmentHostCallback}, overriding the methods
+ * applicable to the host.
+ */
+public abstract class FragmentHostCallback<E> extends FragmentContainer {
+ private final Activity mActivity;
+ final Context mContext;
+ private final Handler mHandler;
+ final int mWindowAnimations;
+ final FragmentManagerImpl mFragmentManager = new FragmentManagerImpl();
+ private ArrayMap<String, LoaderManager> mAllLoaderManagers;
+ private LoaderManagerImpl mLoaderManager;
+ private boolean mCheckedForLoaderManager;
+ private boolean mLoadersStarted;
+
+ public FragmentHostCallback(Context context, Handler handler, int windowAnimations) {
+ this(null /*activity*/, context, handler, windowAnimations);
+ }
+
+ FragmentHostCallback(Activity activity) {
+ this(activity, activity /*context*/, activity.mHandler, 0 /*windowAnimations*/);
+ }
+
+ FragmentHostCallback(Activity activity, Context context, Handler handler,
+ int windowAnimations) {
+ mActivity = activity;
+ mContext = context;
+ mHandler = handler;
+ mWindowAnimations = windowAnimations;
+ }
+
+ /**
+ * Print internal state into the given stream.
+ *
+ * @param prefix Desired prefix to prepend at each line of output.
+ * @param fd The raw file descriptor that the dump is being sent to.
+ * @param writer The PrintWriter to which you should dump your state. This will be closed
+ * for you after you return.
+ * @param args additional arguments to the dump request.
+ */
+ public void onDump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
+ }
+
+ /**
+ * Return {@code true} if the fragment's state needs to be saved.
+ */
+ public boolean onShouldSaveFragmentState(Fragment fragment) {
+ return true;
+ }
+
+ /**
+ * Return a {@link LayoutInflater}.
+ * See {@link Activity#getLayoutInflater()}.
+ */
+ public LayoutInflater onGetLayoutInflater() {
+ return (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ }
+
+ /**
+ * Return {@code true} if the FragmentManager's LayoutInflaterFactory should be used.
+ */
+ public boolean onUseFragmentManagerInflaterFactory() {
+ return false;
+ }
+
+ /**
+ * Return the object that's currently hosting the fragment. If a {@link Fragment}
+ * is hosted by a {@link Activity}, the object returned here should be the same
+ * object returned from {@link Fragment#getActivity()}.
+ */
+ @Nullable
+ public abstract E onGetHost();
+
+ /**
+ * Invalidates the activity's options menu.
+ * See {@link Activity#invalidateOptionsMenu()}
+ */
+ public void onInvalidateOptionsMenu() {
+ }
+
+ /**
+ * Starts a new {@link Activity} from the given fragment.
+ * See {@link Activity#startActivityForResult(Intent, int)}.
+ */
+ public void onStartActivityFromFragment(Fragment fragment, Intent intent, int requestCode,
+ Bundle options) {
+ if (requestCode != -1) {
+ throw new IllegalStateException(
+ "Starting activity with a requestCode requires a FragmentActivity host");
+ }
+ mContext.startActivity(intent);
+ }
+
+ /**
+ * Return {@code true} if there are window animations.
+ */
+ public boolean onHasWindowAnimations() {
+ return true;
+ }
+
+ /**
+ * Return the window animations.
+ */
+ public int onGetWindowAnimations() {
+ return mWindowAnimations;
+ }
+
+ @Nullable
+ @Override
+ public View onFindViewById(int id) {
+ return null;
+ }
+
+ @Override
+ public boolean onHasView() {
+ return true;
+ }
+
+ Activity getActivity() {
+ return mActivity;
+ }
+
+ Context getContext() {
+ return mContext;
+ }
+
+ Handler getHandler() {
+ return mHandler;
+ }
+
+ FragmentManagerImpl getFragmentManagerImpl() {
+ return mFragmentManager;
+ }
+
+ LoaderManagerImpl getLoaderManagerImpl() {
+ if (mLoaderManager != null) {
+ return mLoaderManager;
+ }
+ mCheckedForLoaderManager = true;
+ mLoaderManager = getLoaderManager("(root)", mLoadersStarted, true /*create*/);
+ return mLoaderManager;
+ }
+
+ void inactivateFragment(String who) {
+ //Log.v(TAG, "invalidateSupportFragment: who=" + who);
+ if (mAllLoaderManagers != null) {
+ LoaderManagerImpl lm = (LoaderManagerImpl) mAllLoaderManagers.get(who);
+ if (lm != null && !lm.mRetaining) {
+ lm.doDestroy();
+ mAllLoaderManagers.remove(who);
+ }
+ }
+ }
+
+ void onFragmentInflate(Fragment fragment, AttributeSet attrs, Bundle savedInstanceState) {
+ fragment.onInflate(mContext, attrs, savedInstanceState);
+ }
+
+ void onFragmentAttach(Fragment fragment) {
+ fragment.onAttach(mContext);
+ }
+
+ void doLoaderStart() {
+ if (mLoadersStarted) {
+ return;
+ }
+ mLoadersStarted = true;
+
+ if (mLoaderManager != null) {
+ mLoaderManager.doStart();
+ } else if (!mCheckedForLoaderManager) {
+ mLoaderManager = getLoaderManager("(root)", mLoadersStarted, false);
+ }
+ mCheckedForLoaderManager = true;
+ }
+
+ void doLoaderStop(boolean retain) {
+ if (mLoaderManager == null) {
+ return;
+ }
+
+ if (!mLoadersStarted) {
+ return;
+ }
+ mLoadersStarted = false;
+
+ if (retain) {
+ mLoaderManager.doRetain();
+ } else {
+ mLoaderManager.doStop();
+ }
+ }
+
+ void doLoaderRetain() {
+ if (mLoaderManager == null) {
+ return;
+ }
+ mLoaderManager.doRetain();
+ }
+
+ void doLoaderDestroy() {
+ if (mLoaderManager == null) {
+ return;
+ }
+ mLoaderManager.doDestroy();
+ }
+
+ void reportLoaderStart() {
+ if (mAllLoaderManagers != null) {
+ final int N = mAllLoaderManagers.size();
+ LoaderManagerImpl loaders[] = new LoaderManagerImpl[N];
+ for (int i=N-1; i>=0; i--) {
+ loaders[i] = (LoaderManagerImpl) mAllLoaderManagers.valueAt(i);
+ }
+ for (int i=0; i<N; i++) {
+ LoaderManagerImpl lm = loaders[i];
+ lm.finishRetain();
+ lm.doReportStart();
+ }
+ }
+ }
+
+ LoaderManagerImpl getLoaderManager(String who, boolean started, boolean create) {
+ if (mAllLoaderManagers == null) {
+ mAllLoaderManagers = new ArrayMap<String, LoaderManager>();
+ }
+ LoaderManagerImpl lm = (LoaderManagerImpl) mAllLoaderManagers.get(who);
+ if (lm == null) {
+ if (create) {
+ lm = new LoaderManagerImpl(who, this, started);
+ mAllLoaderManagers.put(who, lm);
+ }
+ } else {
+ lm.updateHostController(this);
+ }
+ return lm;
+ }
+
+ ArrayMap<String, LoaderManager> retainLoaderNonConfig() {
+ boolean retainLoaders = false;
+ if (mAllLoaderManagers != null) {
+ // prune out any loader managers that were already stopped and so
+ // have nothing useful to retain.
+ final int N = mAllLoaderManagers.size();
+ LoaderManagerImpl loaders[] = new LoaderManagerImpl[N];
+ for (int i=N-1; i>=0; i--) {
+ loaders[i] = (LoaderManagerImpl) mAllLoaderManagers.valueAt(i);
+ }
+ for (int i=0; i<N; i++) {
+ LoaderManagerImpl lm = loaders[i];
+ if (lm.mRetaining) {
+ retainLoaders = true;
+ } else {
+ lm.doDestroy();
+ mAllLoaderManagers.remove(lm.mWho);
+ }
+ }
+ }
+
+ if (retainLoaders) {
+ return mAllLoaderManagers;
+ }
+ return null;
+ }
+
+ void restoreLoaderNonConfig(ArrayMap<String, LoaderManager> loaderManagers) {
+ mAllLoaderManagers = loaderManagers;
+ }
+
+ void dumpLoaders(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
+ writer.print(prefix); writer.print("mLoadersStarted=");
+ writer.println(mLoadersStarted);
+ if (mLoaderManager != null) {
+ writer.print(prefix); writer.print("Loader Manager ");
+ writer.print(Integer.toHexString(System.identityHashCode(mLoaderManager)));
+ writer.println(":");
+ mLoaderManager.dump(prefix + " ", fd, writer, args);
+ }
+ }
+}
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 975b20d..62436e9 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -19,9 +19,7 @@
import android.animation.Animator;
import android.animation.AnimatorInflater;
import android.animation.AnimatorListenerAdapter;
-import android.annotation.Nullable;
import android.content.Context;
-import android.annotation.IdRes;
import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.os.Bundle;
@@ -48,6 +46,7 @@
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
/**
* Interface for interacting with {@link Fragment} objects inside of an
@@ -393,15 +392,6 @@
}
/**
- * Callbacks from FragmentManagerImpl to its container.
- */
-interface FragmentContainer {
- @Nullable
- public View findViewById(@IdRes int id);
- public boolean hasView();
-}
-
-/**
* Container for fragments associated with an activity.
*/
final class FragmentManagerImpl extends FragmentManager implements LayoutInflater.Factory2 {
@@ -430,7 +420,8 @@
ArrayList<OnBackStackChangedListener> mBackStackChangeListeners;
int mCurState = Fragment.INITIALIZING;
- Activity mActivity;
+ FragmentHostCallback<?> mHost;
+ FragmentController mController;
FragmentContainer mContainer;
Fragment mParent;
@@ -455,10 +446,10 @@
Log.e(TAG, ex.getMessage());
LogWriter logw = new LogWriter(Log.ERROR, TAG);
PrintWriter pw = new FastPrintWriter(logw, false, 1024);
- if (mActivity != null) {
+ if (mHost != null) {
Log.e(TAG, "Activity state:");
try {
- mActivity.dump(" ", null, pw, new String[] { });
+ mHost.onDump(" ", null, pw, new String[] { });
} catch (Exception e) {
pw.flush();
Log.e(TAG, "Failed dumping state", e);
@@ -490,7 +481,7 @@
public void popBackStack() {
enqueueAction(new Runnable() {
@Override public void run() {
- popBackStackState(mActivity.mHandler, null, -1, 0);
+ popBackStackState(mHost.getHandler(), null, -1, 0);
}
}, false);
}
@@ -499,14 +490,14 @@
public boolean popBackStackImmediate() {
checkStateLoss();
executePendingTransactions();
- return popBackStackState(mActivity.mHandler, null, -1, 0);
+ return popBackStackState(mHost.getHandler(), null, -1, 0);
}
@Override
public void popBackStack(final String name, final int flags) {
enqueueAction(new Runnable() {
@Override public void run() {
- popBackStackState(mActivity.mHandler, name, -1, flags);
+ popBackStackState(mHost.getHandler(), name, -1, flags);
}
}, false);
}
@@ -515,7 +506,7 @@
public boolean popBackStackImmediate(String name, int flags) {
checkStateLoss();
executePendingTransactions();
- return popBackStackState(mActivity.mHandler, name, -1, flags);
+ return popBackStackState(mHost.getHandler(), name, -1, flags);
}
@Override
@@ -525,7 +516,7 @@
}
enqueueAction(new Runnable() {
@Override public void run() {
- popBackStackState(mActivity.mHandler, null, id, flags);
+ popBackStackState(mHost.getHandler(), null, id, flags);
}
}, false);
}
@@ -537,7 +528,7 @@
if (id < 0) {
throw new IllegalArgumentException("Bad id: " + id);
}
- return popBackStackState(mActivity.mHandler, null, id, flags);
+ return popBackStackState(mHost.getHandler(), null, id, flags);
}
@Override
@@ -619,7 +610,7 @@
if (mParent != null) {
DebugUtils.buildShortClassTag(mParent, sb);
} else {
- DebugUtils.buildShortClassTag(mActivity, sb);
+ DebugUtils.buildShortClassTag(mHost, sb);
}
sb.append("}}");
return sb.toString();
@@ -716,7 +707,7 @@
}
writer.print(prefix); writer.println("FragmentManager misc state:");
- writer.print(prefix); writer.print(" mActivity="); writer.println(mActivity);
+ writer.print(prefix); writer.print(" mHost="); writer.println(mHost);
writer.print(prefix); writer.print(" mContainer="); writer.println(mContainer);
if (mParent != null) {
writer.print(prefix); writer.print(" mParent="); writer.println(mParent);
@@ -747,7 +738,7 @@
}
if (fragment.mNextAnim != 0) {
- Animator anim = AnimatorInflater.loadAnimator(mActivity, fragment.mNextAnim);
+ Animator anim = AnimatorInflater.loadAnimator(mHost.getContext(), fragment.mNextAnim);
if (anim != null) {
return anim;
}
@@ -762,14 +753,14 @@
return null;
}
- if (transitionStyle == 0 && mActivity.getWindow() != null) {
- transitionStyle = mActivity.getWindow().getAttributes().windowAnimations;
+ if (transitionStyle == 0 && mHost.onHasWindowAnimations()) {
+ transitionStyle = mHost.onGetWindowAnimations();
}
if (transitionStyle == 0) {
return null;
}
- TypedArray attrs = mActivity.obtainStyledAttributes(transitionStyle,
+ TypedArray attrs = mHost.getContext().obtainStyledAttributes(transitionStyle,
com.android.internal.R.styleable.FragmentAnimation);
int anim = attrs.getResourceId(styleIndex, 0);
attrs.recycle();
@@ -778,7 +769,7 @@
return null;
}
- return AnimatorInflater.loadAnimator(mActivity, anim);
+ return AnimatorInflater.loadAnimator(mHost.getContext(), anim);
}
public void performPendingDeferredStart(Fragment f) {
@@ -848,18 +839,18 @@
}
}
}
- f.mActivity = mActivity;
+ f.mHost = mHost;
f.mParentFragment = mParent;
f.mFragmentManager = mParent != null
- ? mParent.mChildFragmentManager : mActivity.mFragments;
+ ? mParent.mChildFragmentManager : mHost.getFragmentManagerImpl();
f.mCalled = false;
- f.onAttach(mActivity);
+ mHost.onFragmentAttach(f);
if (!f.mCalled) {
throw new SuperNotCalledException("Fragment " + f
+ " did not call through to super.onAttach()");
}
if (f.mParentFragment == null) {
- mActivity.onAttachFragment(f);
+ mHost.onFragmentAttach(f);
}
if (!f.mRetaining) {
@@ -884,7 +875,7 @@
if (!f.mFromLayout) {
ViewGroup container = null;
if (f.mContainerId != 0) {
- container = (ViewGroup)mContainer.findViewById(f.mContainerId);
+ container = (ViewGroup)mContainer.onFindViewById(f.mContainerId);
if (container == null && !f.mRestored) {
throwException(new IllegalArgumentException(
"No view found for id 0x"
@@ -954,7 +945,7 @@
if (f.mView != null) {
// Need to save the current view state if not
// done already.
- if (!mActivity.isFinishing() && f.mSavedViewState == null) {
+ if (!mHost.onShouldSaveFragmentState(f) && f.mSavedViewState == null) {
saveFragmentViewState(f);
}
}
@@ -1030,7 +1021,7 @@
if (!f.mRetaining) {
makeInactive(f);
} else {
- f.mActivity = null;
+ f.mHost = null;
f.mParentFragment = null;
f.mFragmentManager = null;
f.mChildFragmentManager = null;
@@ -1053,7 +1044,7 @@
}
void moveToState(int newState, int transit, int transitStyle, boolean always) {
- if (mActivity == null && newState != Fragment.INITIALIZING) {
+ if (mHost == null && newState != Fragment.INITIALIZING) {
throw new IllegalStateException("No activity");
}
@@ -1078,8 +1069,8 @@
startPendingDeferredFragments();
}
- if (mNeedMenuInvalidate && mActivity != null && mCurState == Fragment.RESUMED) {
- mActivity.invalidateOptionsMenu();
+ if (mNeedMenuInvalidate && mHost != null && mCurState == Fragment.RESUMED) {
+ mHost.onInvalidateOptionsMenu();
mNeedMenuInvalidate = false;
}
}
@@ -1126,7 +1117,7 @@
mAvailIndices = new ArrayList<Integer>();
}
mAvailIndices.add(f.mIndex);
- mActivity.invalidateFragment(f.mWho);
+ mHost.inactivateFragment(f.mWho);
f.initState();
}
@@ -1349,7 +1340,7 @@
checkStateLoss();
}
synchronized (this) {
- if (mDestroyed || mActivity == null) {
+ if (mDestroyed || mHost == null) {
throw new IllegalStateException("Activity has been destroyed");
}
if (mPendingActions == null) {
@@ -1357,8 +1348,8 @@
}
mPendingActions.add(action);
if (mPendingActions.size() == 1) {
- mActivity.mHandler.removeCallbacks(mExecCommit);
- mActivity.mHandler.post(mExecCommit);
+ mHost.getHandler().removeCallbacks(mExecCommit);
+ mHost.getHandler().post(mExecCommit);
}
}
}
@@ -1427,7 +1418,7 @@
throw new IllegalStateException("Recursive entry to executePendingTransactions");
}
- if (Looper.myLooper() != mActivity.mHandler.getLooper()) {
+ if (Looper.myLooper() != mHost.getHandler().getLooper()) {
throw new IllegalStateException("Must be called from main thread of process");
}
@@ -1447,7 +1438,7 @@
}
mPendingActions.toArray(mTmpActions);
mPendingActions.clear();
- mActivity.mHandler.removeCallbacks(mExecCommit);
+ mHost.getHandler().removeCallbacks(mExecCommit);
}
mExecutingActions = true;
@@ -1737,7 +1728,7 @@
return fms;
}
- void restoreAllState(Parcelable state, ArrayList<Fragment> nonConfig) {
+ void restoreAllState(Parcelable state, List<Fragment> nonConfig) {
// If there is no saved state at all, then there can not be
// any nonConfig fragments either, so that is that.
if (state == null) return;
@@ -1758,7 +1749,7 @@
f.mAdded = false;
f.mTarget = null;
if (fs.mSavedFragmentState != null) {
- fs.mSavedFragmentState.setClassLoader(mActivity.getClassLoader());
+ fs.mSavedFragmentState.setClassLoader(mHost.getContext().getClassLoader());
f.mSavedViewState = fs.mSavedFragmentState.getSparseParcelableArray(
FragmentManagerImpl.VIEW_STATE_TAG);
f.mSavedFragmentState = fs.mSavedFragmentState;
@@ -1775,7 +1766,7 @@
for (int i=0; i<fms.mActive.length; i++) {
FragmentState fs = fms.mActive[i];
if (fs != null) {
- Fragment f = fs.instantiate(mActivity, mParent);
+ Fragment f = fs.instantiate(mHost, mParent);
if (DEBUG) Log.v(TAG, "restoreAllState: active #" + i + ": " + f);
mActive.add(f);
// Now that the fragment is instantiated (or came from being
@@ -1851,9 +1842,10 @@
}
}
- public void attachActivity(Activity activity, FragmentContainer container, Fragment parent) {
- if (mActivity != null) throw new IllegalStateException("Already attached");
- mActivity = activity;
+ public void attachController(FragmentHostCallback<?> host, FragmentContainer container,
+ Fragment parent) {
+ if (mHost != null) throw new IllegalStateException("Already attached");
+ mHost = host;
mContainer = container;
mParent = parent;
}
@@ -1898,7 +1890,7 @@
mDestroyed = true;
execPendingActions();
moveToState(Fragment.INITIALIZING, false);
- mActivity = null;
+ mHost = null;
mContainer = null;
mParent = null;
}
@@ -2024,8 +2016,8 @@
@Override
public void invalidateOptionsMenu() {
- if (mActivity != null && mCurState == Fragment.RESUMED) {
- mActivity.invalidateOptionsMenu();
+ if (mHost != null && mCurState == Fragment.RESUMED) {
+ mHost.onInvalidateOptionsMenu();
} else {
mNeedMenuInvalidate = true;
}
@@ -2115,7 +2107,7 @@
fragment.mTag = tag;
fragment.mInLayout = true;
fragment.mFragmentManager = this;
- fragment.onInflate(mActivity, attrs, fragment.mSavedFragmentState);
+ mHost.onFragmentInflate(fragment, attrs, fragment.mSavedFragmentState);
addFragment(fragment, true);
} else if (fragment.mInLayout) {
// A fragment already exists and it is not one we restored from
@@ -2132,7 +2124,7 @@
// from last saved state), then give it the attributes to
// initialize itself.
if (!fragment.mRetaining) {
- fragment.onInflate(mActivity, attrs, fragment.mSavedFragmentState);
+ mHost.onFragmentInflate(fragment, attrs, fragment.mSavedFragmentState);
}
}
diff --git a/core/java/android/app/LoaderManager.java b/core/java/android/app/LoaderManager.java
index b13b24a..f0e35c9 100644
--- a/core/java/android/app/LoaderManager.java
+++ b/core/java/android/app/LoaderManager.java
@@ -214,12 +214,12 @@
final String mWho;
- Activity mActivity;
boolean mStarted;
boolean mRetaining;
boolean mRetainingStarted;
boolean mCreatingLoader;
+ private FragmentHostCallback mHost;
final class LoaderInfo implements Loader.OnLoadCompleteListener<Object>,
Loader.OnLoadCanceledListener<Object> {
@@ -356,15 +356,15 @@
if (mCallbacks != null && mLoader != null && mHaveData && needReset) {
if (DEBUG) Log.v(TAG, " Reseting: " + this);
String lastBecause = null;
- if (mActivity != null) {
- lastBecause = mActivity.mFragments.mNoTransactionsBecause;
- mActivity.mFragments.mNoTransactionsBecause = "onLoaderReset";
+ if (mHost != null) {
+ lastBecause = mHost.mFragmentManager.mNoTransactionsBecause;
+ mHost.mFragmentManager.mNoTransactionsBecause = "onLoaderReset";
}
try {
mCallbacks.onLoaderReset(mLoader);
} finally {
- if (mActivity != null) {
- mActivity.mFragments.mNoTransactionsBecause = lastBecause;
+ if (mHost != null) {
+ mHost.mFragmentManager.mNoTransactionsBecause = lastBecause;
}
}
}
@@ -465,25 +465,25 @@
mInactiveLoaders.remove(mId);
}
- if (mActivity != null && !hasRunningLoaders()) {
- mActivity.mFragments.startPendingDeferredFragments();
+ if (mHost != null && !hasRunningLoaders()) {
+ mHost.mFragmentManager.startPendingDeferredFragments();
}
}
void callOnLoadFinished(Loader<Object> loader, Object data) {
if (mCallbacks != null) {
String lastBecause = null;
- if (mActivity != null) {
- lastBecause = mActivity.mFragments.mNoTransactionsBecause;
- mActivity.mFragments.mNoTransactionsBecause = "onLoadFinished";
+ if (mHost != null) {
+ lastBecause = mHost.mFragmentManager.mNoTransactionsBecause;
+ mHost.mFragmentManager.mNoTransactionsBecause = "onLoadFinished";
}
try {
if (DEBUG) Log.v(TAG, " onLoadFinished in " + loader + ": "
+ loader.dataToString(data));
mCallbacks.onLoadFinished(loader, data);
} finally {
- if (mActivity != null) {
- mActivity.mFragments.mNoTransactionsBecause = lastBecause;
+ if (mHost != null) {
+ mHost.mFragmentManager.mNoTransactionsBecause = lastBecause;
}
}
mDeliveredData = true;
@@ -530,14 +530,14 @@
}
}
- LoaderManagerImpl(String who, Activity activity, boolean started) {
+ LoaderManagerImpl(String who, FragmentHostCallback host, boolean started) {
mWho = who;
- mActivity = activity;
+ mHost = host;
mStarted = started;
}
- void updateActivity(Activity activity) {
- mActivity = activity;
+ void updateHostController(FragmentHostCallback host) {
+ mHost = host;
}
private LoaderInfo createLoader(int id, Bundle args,
@@ -730,8 +730,8 @@
mInactiveLoaders.removeAt(idx);
info.destroy();
}
- if (mActivity != null && !hasRunningLoaders()) {
- mActivity.mFragments.startPendingDeferredFragments();
+ if (mHost != null && !hasRunningLoaders()) {
+ mHost.mFragmentManager.startPendingDeferredFragments();
}
}
@@ -849,7 +849,7 @@
sb.append("LoaderManager{");
sb.append(Integer.toHexString(System.identityHashCode(this)));
sb.append(" in ");
- DebugUtils.buildShortClassTag(mActivity, sb);
+ DebugUtils.buildShortClassTag(mHost, sb);
sb.append("}}");
return sb.toString();
}
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index 779448b..cf96145 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -626,7 +626,13 @@
return 0;
}
- private Handler mHandler = new Handler() {
+ private Handler mHandler;
+
+ private class MyHandler extends Handler {
+ private MyHandler(Context context) {
+ super(context.getMainLooper());
+ }
+
public void handleMessage(android.os.Message msg) {
switch(msg.what) {
case MSG_ENROLL_RESULT:
@@ -711,6 +717,7 @@
if (mService == null) {
Slog.v(TAG, "FingerprintManagerService was null");
}
+ mHandler = new MyHandler(context);
}
private int getCurrentUserId() {
diff --git a/core/java/android/security/keymaster/KeymasterDefs.java b/core/java/android/security/keymaster/KeymasterDefs.java
index d8834fe..0e2b8ba 100644
--- a/core/java/android/security/keymaster/KeymasterDefs.java
+++ b/core/java/android/security/keymaster/KeymasterDefs.java
@@ -238,6 +238,8 @@
sErrorCodeToString.put(KM_ERROR_UNSUPPORTED_EC_FIELD, "Unsupported EC field");
sErrorCodeToString.put(KM_ERROR_MISSING_NONCE, "Required IV missing");
sErrorCodeToString.put(KM_ERROR_INVALID_NONCE, "Invalid IV");
+ sErrorCodeToString.put(KM_ERROR_CALLER_NONCE_PROHIBITED,
+ "Caller-provided IV not permitted");
sErrorCodeToString.put(KM_ERROR_UNIMPLEMENTED, "Not implemented");
sErrorCodeToString.put(KM_ERROR_UNKNOWN_ERROR, "Unknown error");
}
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index 457d6ad..1503728 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -946,25 +946,21 @@
attrs, R.styleable.Include);
final int id = a.getResourceId(R.styleable.Include_id, View.NO_ID);
final int visibility = a.getInt(R.styleable.Include_visibility, -1);
- final boolean hasWidth = a.hasValue(R.styleable.Include_layout_width);
- final boolean hasHeight = a.hasValue(R.styleable.Include_layout_height);
a.recycle();
- // We try to load the layout params set in the <include /> tag. If
- // they don't exist, we will rely on the layout params set in the
- // included XML file.
- // During a layoutparams generation, a runtime exception is thrown
- // if either layout_width or layout_height is missing. We catch
- // this exception and set localParams accordingly: true means we
- // successfully loaded layout params from the <include /> tag,
- // false means we need to rely on the included layout params.
+ // We try to load the layout params set in the <include /> tag.
+ // If the parent can't generate layout params (ex. missing width
+ // or height for the framework ViewGroups, though this is not
+ // necessarily true of all ViewGroups) then we expect it to throw
+ // a runtime exception.
+ // We catch this exception and set localParams accordingly: true
+ // means we successfully loaded layout params from the <include>
+ // tag, false means we need to rely on the included layout params.
ViewGroup.LayoutParams params = null;
- if (hasWidth && hasHeight) {
- try {
- params = group.generateLayoutParams(attrs);
- } catch (RuntimeException e) {
- // Ignore, just fail over to child attrs.
- }
+ try {
+ params = group.generateLayoutParams(attrs);
+ } catch (RuntimeException e) {
+ // Ignore, just fail over to child attrs.
}
if (params == null) {
params = group.generateLayoutParams(childAttrs);
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 4c4a39d..d4069a1 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -261,7 +261,7 @@
SkBitmap* outputBitmap = NULL;
unsigned int existingBufferSize = 0;
if (javaBitmap != NULL) {
- outputBitmap = GraphicsJNI::getSkBitmap(env, javaBitmap);
+ outputBitmap = GraphicsJNI::getSkBitmapDeprecated(env, javaBitmap);
if (outputBitmap->isImmutable()) {
ALOGW("Unable to reuse an immutable bitmap as an image decoder target.");
javaBitmap = NULL;
diff --git a/core/jni/android/graphics/BitmapRegionDecoder.cpp b/core/jni/android/graphics/BitmapRegionDecoder.cpp
index 3525d07..aeea808 100644
--- a/core/jni/android/graphics/BitmapRegionDecoder.cpp
+++ b/core/jni/android/graphics/BitmapRegionDecoder.cpp
@@ -217,7 +217,7 @@
if (tileBitmap != NULL) {
// Re-use bitmap.
- bitmap = GraphicsJNI::getSkBitmap(env, tileBitmap);
+ bitmap = GraphicsJNI::getSkBitmapDeprecated(env, tileBitmap);
}
if (bitmap == NULL) {
bitmap = new SkBitmap;
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index 44037dd..f793df1 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -338,7 +338,7 @@
return static_cast<SkColorType>(gConfig2ColorType[legacyConfig]);
}
-SkBitmap* GraphicsJNI::getSkBitmap(JNIEnv* env, jobject bitmap) {
+SkBitmap* GraphicsJNI::getSkBitmapDeprecated(JNIEnv* env, jobject bitmap) {
SkASSERT(env);
SkASSERT(bitmap);
SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
@@ -348,6 +348,19 @@
return b;
}
+void GraphicsJNI::getSkBitmap(JNIEnv* env, jobject bitmap, SkBitmap* outBitmap) {
+ // TODO: We have to copy from the existing bitmap due to rowBytes not
+ // being updated on the SkPixelRef at reconfigure time. This is a short term
+ // problem that will be fixed with the specialized wrapper
+ *outBitmap = *getSkBitmapDeprecated(env, bitmap);
+}
+
+SkPixelRef* GraphicsJNI::getSkPixelRef(JNIEnv* env, jobject bitmap) {
+ jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_skBitmapPtr);
+ SkBitmap* b = reinterpret_cast<SkBitmap*>(bitmapHandle);
+ return b->pixelRef();
+}
+
SkColorType GraphicsJNI::getNativeBitmapColorType(JNIEnv* env, jobject jconfig) {
SkASSERT(env);
if (NULL == jconfig) {
diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h
index d73507e..8eb43f8 100644
--- a/core/jni/android/graphics/GraphicsJNI.h
+++ b/core/jni/android/graphics/GraphicsJNI.h
@@ -49,7 +49,9 @@
static void point_to_jpointf(const SkPoint& point, JNIEnv*, jobject jpointf);
static android::Canvas* getNativeCanvas(JNIEnv*, jobject canvas);
- static SkBitmap* getSkBitmap(JNIEnv*, jobject bitmap);
+ static SkBitmap* getSkBitmapDeprecated(JNIEnv*, jobject bitmap);
+ static void getSkBitmap(JNIEnv*, jobject bitmap, SkBitmap* outBitmap);
+ static SkPixelRef* getSkPixelRef(JNIEnv*, jobject bitmap);
static SkRegion* getNativeRegion(JNIEnv*, jobject region);
// Given the 'native' long held by the Rasterizer.java object, return a
diff --git a/core/jni/android/graphics/pdf/PdfRenderer.cpp b/core/jni/android/graphics/pdf/PdfRenderer.cpp
index fc98cf9..876bea4 100644
--- a/core/jni/android/graphics/pdf/PdfRenderer.cpp
+++ b/core/jni/android/graphics/pdf/PdfRenderer.cpp
@@ -243,19 +243,21 @@
}
static void nativeRenderPage(JNIEnv* env, jclass thiz, jlong documentPtr, jlong pagePtr,
- jlong bitmapPtr, jint destLeft, jint destTop, jint destRight, jint destBottom,
+ jobject jbitmap, jint destLeft, jint destTop, jint destRight, jint destBottom,
jlong matrixPtr, jint renderMode) {
FPDF_PAGE page = reinterpret_cast<FPDF_PAGE>(pagePtr);
- SkBitmap* skBitmap = reinterpret_cast<SkBitmap*>(bitmapPtr);
SkMatrix* skMatrix = reinterpret_cast<SkMatrix*>(matrixPtr);
- skBitmap->lockPixels();
+ SkBitmap skBitmap;
+ GraphicsJNI::getSkBitmap(env, jbitmap, &skBitmap);
- const int stride = skBitmap->width() * 4;
+ SkAutoLockPixels alp(skBitmap);
- FPDF_BITMAP bitmap = FPDFBitmap_CreateEx(skBitmap->width(), skBitmap->height(),
- FPDFBitmap_BGRA, skBitmap->getPixels(), stride);
+ const int stride = skBitmap.width() * 4;
+
+ FPDF_BITMAP bitmap = FPDFBitmap_CreateEx(skBitmap.width(), skBitmap.height(),
+ FPDFBitmap_BGRA, skBitmap.getPixels(), stride);
if (!bitmap) {
ALOGE("Erorr creating bitmap");
@@ -278,8 +280,7 @@
renderPageBitmap(bitmap, page, destLeft, destTop, destRight,
destBottom, skMatrix, renderFlags);
- skBitmap->notifyPixelsChanged();
- skBitmap->unlockPixels();
+ skBitmap.notifyPixelsChanged();
}
static JNINativeMethod gPdfRenderer_Methods[] = {
@@ -287,7 +288,7 @@
{"nativeClose", "(J)V", (void*) nativeClose},
{"nativeGetPageCount", "(J)I", (void*) nativeGetPageCount},
{"nativeScaleForPrinting", "(J)Z", (void*) nativeScaleForPrinting},
- {"nativeRenderPage", "(JJJIIIIJI)V", (void*) nativeRenderPage},
+ {"nativeRenderPage", "(JJLandroid/graphics/Bitmap;IIIIJI)V", (void*) nativeRenderPage},
{"nativeOpenPageAndGetSize", "(JILandroid/graphics/Point;)J", (void*) nativeOpenPageAndGetSize},
{"nativeClosePage", "(J)V", (void*) nativeClosePage}
};
diff --git a/core/jni/android/opengl/util.cpp b/core/jni/android/opengl/util.cpp
index 5c2d0d0..bce2b33 100644
--- a/core/jni/android/opengl/util.cpp
+++ b/core/jni/android/opengl/util.cpp
@@ -618,23 +618,25 @@
static jint util_getInternalFormat(JNIEnv *env, jclass clazz,
jobject jbitmap)
{
- SkBitmap const * nativeBitmap = GraphicsJNI::getSkBitmap(env, jbitmap);
- return getInternalFormat(nativeBitmap->colorType());
+ SkBitmap nativeBitmap;
+ GraphicsJNI::getSkBitmap(env, jbitmap, &nativeBitmap);
+ return getInternalFormat(nativeBitmap.colorType());
}
static jint util_getType(JNIEnv *env, jclass clazz,
jobject jbitmap)
{
- SkBitmap const * nativeBitmap = GraphicsJNI::getSkBitmap(env, jbitmap);
- return getType(nativeBitmap->colorType());
+ SkBitmap nativeBitmap;
+ GraphicsJNI::getSkBitmap(env, jbitmap, &nativeBitmap);
+ return getType(nativeBitmap.colorType());
}
static jint util_texImage2D(JNIEnv *env, jclass clazz,
jint target, jint level, jint internalformat,
jobject jbitmap, jint type, jint border)
{
- SkBitmap const * nativeBitmap = GraphicsJNI::getSkBitmap(env, jbitmap);
- const SkBitmap& bitmap(*nativeBitmap);
+ SkBitmap bitmap;
+ GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
SkColorType colorType = bitmap.colorType();
if (internalformat < 0) {
internalformat = getInternalFormat(colorType);
@@ -680,8 +682,8 @@
jint target, jint level, jint xoffset, jint yoffset,
jobject jbitmap, jint format, jint type)
{
- SkBitmap const * nativeBitmap = GraphicsJNI::getSkBitmap(env, jbitmap);
- const SkBitmap& bitmap(*nativeBitmap);
+ SkBitmap bitmap;
+ GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
SkColorType colorType = bitmap.colorType();
if (format < 0) {
format = getInternalFormat(colorType);
diff --git a/core/jni/android_graphics_Canvas.cpp b/core/jni/android_graphics_Canvas.cpp
index 3ae829b..5d08532 100644
--- a/core/jni/android_graphics_Canvas.cpp
+++ b/core/jni/android_graphics_Canvas.cpp
@@ -42,7 +42,7 @@
static jlong initRaster(JNIEnv* env, jobject, jobject jbitmap) {
SkBitmap* bitmap = nullptr;
if (jbitmap != NULL) {
- bitmap = GraphicsJNI::getSkBitmap(env, jbitmap);
+ bitmap = GraphicsJNI::getSkBitmapDeprecated(env, jbitmap);
}
return reinterpret_cast<jlong>(Canvas::create_canvas(
bitmap ? *bitmap : SkBitmap()));
@@ -53,7 +53,7 @@
static void setBitmap(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap) {
SkBitmap* bitmap = nullptr;
if (jbitmap != NULL) {
- bitmap = GraphicsJNI::getSkBitmap(env, jbitmap);
+ bitmap = GraphicsJNI::getSkBitmapDeprecated(env, jbitmap);
}
get_canvas(canvasHandle)->setBitmap(bitmap ? *bitmap : SkBitmap());
}
diff --git a/core/jni/android_view_PointerIcon.cpp b/core/jni/android_view_PointerIcon.cpp
index f6d9a1a..d04adbf 100644
--- a/core/jni/android_view_PointerIcon.cpp
+++ b/core/jni/android_view_PointerIcon.cpp
@@ -80,10 +80,7 @@
jobject bitmapObj = env->GetObjectField(loadedPointerIconObj, gPointerIconClassInfo.mBitmap);
if (bitmapObj) {
- SkBitmap* bitmap = GraphicsJNI::getSkBitmap(env, bitmapObj);
- if (bitmap) {
- outPointerIcon->bitmap = *bitmap; // use a shared pixel ref
- }
+ GraphicsJNI::getSkBitmap(env, bitmapObj, &(outPointerIcon->bitmap));
env->DeleteLocalRef(bitmapObj);
}
diff --git a/core/jni/com_google_android_gles_jni_EGLImpl.cpp b/core/jni/com_google_android_gles_jni_EGLImpl.cpp
index 7080e2a..baeb7dd 100644
--- a/core/jni/com_google_android_gles_jni_EGLImpl.cpp
+++ b/core/jni/com_google_android_gles_jni_EGLImpl.cpp
@@ -277,8 +277,9 @@
EGLConfig cnf = getConfig(_env, config);
jint* base = 0;
- SkBitmap const * nativeBitmap = GraphicsJNI::getSkBitmap(_env, native_pixmap);
- SkPixelRef* ref = nativeBitmap ? nativeBitmap->pixelRef() : 0;
+ SkBitmap nativeBitmap;
+ GraphicsJNI::getSkBitmap(_env, native_pixmap, &nativeBitmap);
+ SkPixelRef* ref = nativeBitmap.pixelRef();
if (ref == NULL) {
jniThrowException(_env, "java/lang/IllegalArgumentException", "Bitmap has no PixelRef");
return;
@@ -289,10 +290,10 @@
egl_native_pixmap_t pixmap;
pixmap.version = sizeof(pixmap);
- pixmap.width = nativeBitmap->width();
- pixmap.height = nativeBitmap->height();
- pixmap.stride = nativeBitmap->rowBytes() / nativeBitmap->bytesPerPixel();
- pixmap.format = convertPixelFormat(nativeBitmap->colorType());
+ pixmap.width = nativeBitmap.width();
+ pixmap.height = nativeBitmap.height();
+ pixmap.stride = nativeBitmap.rowBytes() / nativeBitmap.bytesPerPixel();
+ pixmap.format = convertPixelFormat(nativeBitmap.colorType());
pixmap.data = (uint8_t*)ref->pixels();
base = beginNativeAttribList(_env, attrib_list);
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 702f720..52b31b2 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2725,12 +2725,11 @@
<attr name="value" />
</declare-styleable>
- <!-- Attributes that can be assigned to an <include> tag. -->
+ <!-- Attributes that can be assigned to an <include> tag.
+ @hide -->
<declare-styleable name="Include">
<attr name="id" />
<attr name="visibility" />
- <attr name="layout_width" />
- <attr name="layout_height" />
</declare-styleable>
<!-- Attributes that can be used with a {@link android.view.ViewGroup} or any
diff --git a/graphics/java/android/graphics/pdf/PdfRenderer.java b/graphics/java/android/graphics/pdf/PdfRenderer.java
index b32dcc6..feb8052 100644
--- a/graphics/java/android/graphics/pdf/PdfRenderer.java
+++ b/graphics/java/android/graphics/pdf/PdfRenderer.java
@@ -380,7 +380,7 @@
final long transformPtr = (transform != null) ? transform.native_instance : 0;
- nativeRenderPage(mNativeDocument, mNativePage, destination.getSkBitmap(), contentLeft,
+ nativeRenderPage(mNativeDocument, mNativePage, destination, contentLeft,
contentTop, contentRight, contentBottom, transformPtr, renderMode);
}
@@ -425,7 +425,7 @@
private static native void nativeClose(long documentPtr);
private static native int nativeGetPageCount(long documentPtr);
private static native boolean nativeScaleForPrinting(long documentPtr);
- private static native void nativeRenderPage(long documentPtr, long pagePtr, long destPtr,
+ private static native void nativeRenderPage(long documentPtr, long pagePtr, Bitmap dest,
int destLeft, int destTop, int destRight, int destBottom, long matrixPtr, int renderMode);
private static native long nativeOpenPageAndGetSize(long documentPtr, int pageIndex,
Point outSize);
diff --git a/keystore/java/android/security/KeyStoreCryptoOperationUtils.java b/keystore/java/android/security/KeyStoreCryptoOperationUtils.java
index 313b527..e5933ad 100644
--- a/keystore/java/android/security/KeyStoreCryptoOperationUtils.java
+++ b/keystore/java/android/security/KeyStoreCryptoOperationUtils.java
@@ -74,6 +74,8 @@
switch (beginOpResultCode) {
case KeymasterDefs.KM_ERROR_INVALID_NONCE:
return new InvalidAlgorithmParameterException("Invalid IV");
+ case KeymasterDefs.KM_ERROR_CALLER_NONCE_PROHIBITED:
+ return new InvalidAlgorithmParameterException("Caller-provided IV not permitted");
}
// General cases
diff --git a/media/jni/android_media_MediaMetadataRetriever.cpp b/media/jni/android_media_MediaMetadataRetriever.cpp
index 88a6771..59fb6d6 100644
--- a/media/jni/android_media_MediaMetadataRetriever.cpp
+++ b/media/jni/android_media_MediaMetadataRetriever.cpp
@@ -299,15 +299,16 @@
return NULL;
}
- SkBitmap *bitmap = GraphicsJNI::getSkBitmap(env, jBitmap);
+ SkBitmap bitmap;
+ GraphicsJNI::getSkBitmap(env, jBitmap, &bitmap);
- bitmap->lockPixels();
- rotate((uint16_t*)bitmap->getPixels(),
+ bitmap.lockPixels();
+ rotate((uint16_t*)bitmap.getPixels(),
(uint16_t*)((char*)videoFrame + sizeof(VideoFrame)),
videoFrame->mWidth,
videoFrame->mHeight,
videoFrame->mRotationAngle);
- bitmap->unlockPixels();
+ bitmap.unlockPixels();
if (videoFrame->mDisplayWidth != videoFrame->mWidth ||
videoFrame->mDisplayHeight != videoFrame->mHeight) {
diff --git a/native/graphics/jni/bitmap.cpp b/native/graphics/jni/bitmap.cpp
index ddb01a0..0521833 100644
--- a/native/graphics/jni/bitmap.cpp
+++ b/native/graphics/jni/bitmap.cpp
@@ -27,18 +27,16 @@
return ANDROID_BITMAP_RESULT_BAD_PARAMETER;
}
- SkBitmap* bm = GraphicsJNI::getSkBitmap(env, jbitmap);
- if (NULL == bm) {
- return ANDROID_BITMAP_RESULT_JNI_EXCEPTION;
- }
+ SkBitmap bm;
+ GraphicsJNI::getSkBitmap(env, jbitmap, &bm);
if (info) {
- info->width = bm->width();
- info->height = bm->height();
- info->stride = bm->rowBytes();
+ info->width = bm.width();
+ info->height = bm.height();
+ info->stride = bm.rowBytes();
info->flags = 0;
- switch (bm->colorType()) {
+ switch (bm.colorType()) {
case kN32_SkColorType:
info->format = ANDROID_BITMAP_FORMAT_RGBA_8888;
break;
@@ -64,17 +62,18 @@
return ANDROID_BITMAP_RESULT_BAD_PARAMETER;
}
- SkBitmap* bm = GraphicsJNI::getSkBitmap(env, jbitmap);
- if (NULL == bm) {
+ SkPixelRef* pixelRef = GraphicsJNI::getSkPixelRef(env, jbitmap);
+ if (!pixelRef) {
return ANDROID_BITMAP_RESULT_JNI_EXCEPTION;
}
- bm->lockPixels();
- void* addr = bm->getPixels();
+ pixelRef->lockPixels();
+ void* addr = pixelRef->pixels();
if (NULL == addr) {
- bm->unlockPixels();
+ pixelRef->unlockPixels();
return ANDROID_BITMAP_RESULT_ALLOCATION_FAILED;
}
+ pixelRef->ref();
if (addrPtr) {
*addrPtr = addr;
@@ -87,8 +86,8 @@
return ANDROID_BITMAP_RESULT_BAD_PARAMETER;
}
- SkBitmap* bm = GraphicsJNI::getSkBitmap(env, jbitmap);
- if (NULL == bm) {
+ SkPixelRef* pixelRef = GraphicsJNI::getSkPixelRef(env, jbitmap);
+ if (!pixelRef) {
return ANDROID_BITMAP_RESULT_JNI_EXCEPTION;
}
@@ -96,9 +95,11 @@
// bitmaps. Note that this will slow down read-only accesses to the
// bitmaps, but the NDK methods are primarily intended to be used for
// writes.
- bm->notifyPixelsChanged();
+ pixelRef->notifyPixelsChanged();
- bm->unlockPixels();
+ pixelRef->unlockPixels();
+ pixelRef->unref();
+
return ANDROID_BITMAP_RESULT_SUCCESS;
}
diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp
index 1c8521b..5ef807d 100644
--- a/rs/jni/android_renderscript_RenderScript.cpp
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -1102,9 +1102,8 @@
nAllocationCreateFromBitmap(JNIEnv *_env, jobject _this, jlong con, jlong type, jint mip,
jobject jbitmap, jint usage)
{
- SkBitmap const * nativeBitmap =
- GraphicsJNI::getSkBitmap(_env, jbitmap);
- const SkBitmap& bitmap(*nativeBitmap);
+ SkBitmap bitmap;
+ GraphicsJNI::getSkBitmap(_env, jbitmap, &bitmap);
bitmap.lockPixels();
const void* ptr = bitmap.getPixels();
@@ -1119,9 +1118,8 @@
nAllocationCreateBitmapBackedAllocation(JNIEnv *_env, jobject _this, jlong con, jlong type,
jint mip, jobject jbitmap, jint usage)
{
- SkBitmap const * nativeBitmap =
- GraphicsJNI::getSkBitmap(_env, jbitmap);
- const SkBitmap& bitmap(*nativeBitmap);
+ SkBitmap bitmap;
+ GraphicsJNI::getSkBitmap(_env, jbitmap, &bitmap);
bitmap.lockPixels();
const void* ptr = bitmap.getPixels();
@@ -1136,9 +1134,8 @@
nAllocationCubeCreateFromBitmap(JNIEnv *_env, jobject _this, jlong con, jlong type, jint mip,
jobject jbitmap, jint usage)
{
- SkBitmap const * nativeBitmap =
- GraphicsJNI::getSkBitmap(_env, jbitmap);
- const SkBitmap& bitmap(*nativeBitmap);
+ SkBitmap bitmap;
+ GraphicsJNI::getSkBitmap(_env, jbitmap, &bitmap);
bitmap.lockPixels();
const void* ptr = bitmap.getPixels();
@@ -1152,9 +1149,8 @@
static void
nAllocationCopyFromBitmap(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jobject jbitmap)
{
- SkBitmap const * nativeBitmap =
- GraphicsJNI::getSkBitmap(_env, jbitmap);
- const SkBitmap& bitmap(*nativeBitmap);
+ SkBitmap bitmap;
+ GraphicsJNI::getSkBitmap(_env, jbitmap, &bitmap);
int w = bitmap.width();
int h = bitmap.height();
@@ -1169,9 +1165,8 @@
static void
nAllocationCopyToBitmap(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jobject jbitmap)
{
- SkBitmap const * nativeBitmap =
- GraphicsJNI::getSkBitmap(_env, jbitmap);
- const SkBitmap& bitmap(*nativeBitmap);
+ SkBitmap bitmap;
+ GraphicsJNI::getSkBitmap(_env, jbitmap, &bitmap);
bitmap.lockPixels();
void* ptr = bitmap.getPixels();
diff --git a/services/core/jni/com_android_server_AssetAtlasService.cpp b/services/core/jni/com_android_server_AssetAtlasService.cpp
index ad1d0f5..3d8905d 100644
--- a/services/core/jni/com_android_server_AssetAtlasService.cpp
+++ b/services/core/jni/com_android_server_AssetAtlasService.cpp
@@ -64,7 +64,7 @@
static jboolean com_android_server_AssetAtlasService_upload(JNIEnv* env, jobject,
jobject graphicBuffer, jobject bitmapHandle) {
- SkBitmap& bitmap = *GraphicsJNI::getSkBitmap(env, bitmapHandle);
+ SkBitmap& bitmap = *GraphicsJNI::getSkBitmapDeprecated(env, bitmapHandle);
SkAutoLockPixels alp(bitmap);
// The goal of this method is to copy the bitmap into the GraphicBuffer