2828import android .os .Parcelable ;
2929import android .support .annotation .CallSuper ;
3030import android .support .annotation .IdRes ;
31+ import android .support .annotation .NonNull ;
3132import android .support .annotation .StringRes ;
3233import android .support .v4 .util .DebugUtils ;
3334import android .support .v4 .util .LogWriter ;
@@ -366,13 +367,18 @@ public static void enableDebugLogging(boolean enabled) {
366367
367368 abstract int getActivityRequestCode (Fragment fragment );
368369 abstract void onActivityResult (int requestCode , int resultCode , Intent data );
370+
371+ abstract int getPermissionsRequestCode (Fragment fragment );
372+ abstract void onRequestPermissionsResult (int requestCode , @ NonNull String [] permissions ,
373+ @ NonNull int [] grantResults );
369374}
370375
371376final class FragmentManagerState implements Parcelable {
372377 FragmentState [] mActive ;
373378 int [] mAdded ;
374379 BackStackState [] mBackStack ;
375380 ActivityRequest [] mPendingActivityRequests ;
381+ PermissionsRequest [] mPendingPermissionsRequests ;
376382
377383 public FragmentManagerState () {
378384 }
@@ -382,6 +388,7 @@ public FragmentManagerState(Parcel in) {
382388 mAdded = in .createIntArray ();
383389 mBackStack = in .createTypedArray (BackStackState .CREATOR );
384390 mPendingActivityRequests = in .createTypedArray (ActivityRequest .CREATOR );
391+ mPendingPermissionsRequests = in .createTypedArray (PermissionsRequest .CREATOR );
385392 }
386393
387394 public int describeContents () {
@@ -393,6 +400,7 @@ public void writeToParcel(Parcel dest, int flags) {
393400 dest .writeIntArray (mAdded );
394401 dest .writeTypedArray (mBackStack , flags );
395402 dest .writeTypedArray (mPendingActivityRequests , flags );
403+ dest .writeTypedArray (mPendingPermissionsRequests , flags );
396404 }
397405
398406 public static final Parcelable .Creator <FragmentManagerState > CREATOR
@@ -448,6 +456,47 @@ public ActivityRequest[] newArray(int size) {
448456 };
449457}
450458
459+ final class PermissionsRequest implements Parcelable {
460+ final int mFragmentIndex ;
461+ final int mRequestIndex ;
462+ final int mChildRequestIndex ;
463+
464+ PermissionsRequest (int fragmentIndex , int requestIndex , int childRequestIndex ) {
465+ mFragmentIndex = fragmentIndex ;
466+ mRequestIndex = requestIndex ;
467+ mChildRequestIndex = childRequestIndex ;
468+ }
469+
470+ PermissionsRequest (Parcel in ) {
471+ mFragmentIndex = in .readInt ();
472+ mRequestIndex = in .readInt ();
473+ mChildRequestIndex = in .readInt ();
474+ }
475+
476+ @ Override
477+ public int describeContents () {
478+ return 0 ;
479+ }
480+
481+ @ Override
482+ public void writeToParcel (Parcel dest , int flags ) {
483+ dest .writeInt (mFragmentIndex );
484+ dest .writeInt (mRequestIndex );
485+ dest .writeInt (mChildRequestIndex );
486+ }
487+
488+ public static final Parcelable .Creator <PermissionsRequest > CREATOR
489+ = new Parcelable .Creator <PermissionsRequest >() {
490+ public PermissionsRequest createFromParcel (Parcel in ) {
491+ return new PermissionsRequest (in );
492+ }
493+
494+ public PermissionsRequest [] newArray (int size ) {
495+ return new PermissionsRequest [size ];
496+ }
497+ };
498+ }
499+
451500/**
452501 * Container for fragments associated with an activity.
453502 */
@@ -537,6 +586,8 @@ public void onAnimationRepeat(Animation animation) {
537586 ArrayList <Fragment > mCreatedMenus ;
538587 ArrayList <ActivityRequest > mPendingActivityRequests ;
539588 ArrayList <Integer > mAvailRequestIndices ;
589+ ArrayList <PermissionsRequest > mPendingPermissionsRequests ;
590+ ArrayList <Integer > mAvailPermissionsRequestIndices ;
540591
541592 // Must be accessed while locked.
542593 ArrayList <BackStackRecord > mBackStackIndices ;
@@ -945,6 +996,77 @@ private boolean dispatchOnActivityResult(int requestIndex, int requestCode, int
945996 }
946997 }
947998
999+ @ Override
1000+ int getPermissionsRequestCode (Fragment fragment ) {
1001+ return getPermissionsRequestIndex (fragment , -1 ) + 1 ;
1002+ }
1003+
1004+ private int getPermissionsRequestIndex (Fragment fragment , int childRequestIndex ) {
1005+ final PermissionsRequest request ;
1006+
1007+ if (mAvailPermissionsRequestIndices == null || mAvailPermissionsRequestIndices .isEmpty ()) {
1008+ if (mPendingPermissionsRequests == null ) {
1009+ mPendingPermissionsRequests = new ArrayList <PermissionsRequest >();
1010+ }
1011+
1012+ if (mPendingPermissionsRequests .size () > 0xff ) {
1013+ throw new IllegalStateException ("Over 0xff pending permissions requests in " + fragment );
1014+ }
1015+
1016+ request = new PermissionsRequest (fragment .mIndex , mPendingPermissionsRequests .size (), childRequestIndex );
1017+ mPendingPermissionsRequests .add (request );
1018+ } else {
1019+ request = new PermissionsRequest (fragment .mIndex , mAvailPermissionsRequestIndices .remove (mAvailPermissionsRequestIndices .size () - 1 ), childRequestIndex );
1020+ mPendingPermissionsRequests .set (request .mRequestIndex , request );
1021+ }
1022+
1023+ Fragment parent = fragment .getParentFragment ();
1024+ if (parent != null ) {
1025+ return parent .mFragmentManager .getPermissionsRequestIndex (parent , request .mRequestIndex );
1026+ } else {
1027+ return request .mRequestIndex ;
1028+ }
1029+ }
1030+
1031+ @ Override
1032+ void onRequestPermissionsResult (int requestCode , @ NonNull String [] permissions ,
1033+ @ NonNull int [] grantResults ) {
1034+ if (!dispatchOnRequestPermissionsResult ((requestCode >>8 ) - 1 , requestCode &0xff ,
1035+ permissions , grantResults )) {
1036+ Log .w (TAG , "No fragment exists for requestCode: 0x" + Integer .toHexString (requestCode ));
1037+ }
1038+ }
1039+
1040+ private boolean dispatchOnRequestPermissionsResult (int requestIndex , int requestCode ,
1041+ @ NonNull String [] permissions ,
1042+ @ NonNull int [] grantResults ) {
1043+ if (!checkElement (mPendingPermissionsRequests , requestIndex )) {
1044+ return false ;
1045+ }
1046+
1047+ PermissionsRequest resultRequest = mPendingPermissionsRequests .get (requestIndex );
1048+ if (!checkElement (mActive , resultRequest .mFragmentIndex )) {
1049+ return false ;
1050+ }
1051+
1052+ Fragment fragment = mActive .get (resultRequest .mFragmentIndex );
1053+ if (resultRequest .mChildRequestIndex != -1 ) {
1054+ mPendingPermissionsRequests .set (requestIndex , null );
1055+ if (mAvailPermissionsRequestIndices == null ) {
1056+ mAvailPermissionsRequestIndices = new ArrayList <Integer >();
1057+ }
1058+ mAvailPermissionsRequestIndices .add (requestIndex );
1059+
1060+ return fragment .mChildFragmentManager .dispatchOnRequestPermissionsResult (
1061+ resultRequest .mChildRequestIndex ,
1062+ requestCode , permissions , grantResults
1063+ );
1064+ } else {
1065+ fragment .onRequestPermissionsResult (requestCode , permissions , grantResults );
1066+ return true ;
1067+ }
1068+ }
1069+
9481070 private boolean checkElement (ArrayList <?> list , int index ) {
9491071 return list != null && index < list .size () && list .get (index ) != null ;
9501072 }
@@ -2028,11 +2150,18 @@ Parcelable saveAllState() {
20282150 pendingActivityRequests = mPendingActivityRequests .toArray (new ActivityRequest [mPendingActivityRequests .size ()]);
20292151 }
20302152
2153+ // Save pending permissions requests
2154+ PermissionsRequest [] pendingPermissionsRequests = null ;
2155+ if (mPendingPermissionsRequests != null ) {
2156+ pendingPermissionsRequests = mPendingPermissionsRequests .toArray (new PermissionsRequest [mPendingPermissionsRequests .size ()]);
2157+ }
2158+
20312159 FragmentManagerState fms = new FragmentManagerState ();
20322160 fms .mActive = active ;
20332161 fms .mAdded = added ;
20342162 fms .mBackStack = backStack ;
20352163 fms .mPendingActivityRequests = pendingActivityRequests ;
2164+ fms .mPendingPermissionsRequests = pendingPermissionsRequests ;
20362165 return fms ;
20372166 }
20382167
@@ -2163,6 +2292,22 @@ void restoreAllState(Parcelable state, List<Fragment> nonConfig) {
21632292 }
21642293 mPendingActivityRequests = new ArrayList <ActivityRequest >(Arrays .asList (fms .mPendingActivityRequests ));
21652294 }
2295+
2296+ // Restore pending permissions requests
2297+ if (fms .mPendingPermissionsRequests != null ) {
2298+ mPendingPermissionsRequests = new ArrayList <PermissionsRequest >();
2299+ if (mAvailPermissionsRequestIndices != null ) {
2300+ mAvailPermissionsRequestIndices .clear ();
2301+ } else {
2302+ mAvailPermissionsRequestIndices = new ArrayList <Integer >();
2303+ }
2304+ for (int i =0 ; i <fms .mPendingPermissionsRequests .length ; i ++) {
2305+ if (fms .mPendingPermissionsRequests [i ] == null ) {
2306+ mAvailPermissionsRequestIndices .add (i );
2307+ }
2308+ }
2309+ mPendingPermissionsRequests = new ArrayList <PermissionsRequest >(Arrays .asList (fms .mPendingPermissionsRequests ));
2310+ }
21662311 }
21672312
21682313 public void attachController (FragmentHostCallback host ,
0 commit comments