1 /*
2  * Copyright 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.credentials.ui;
18 
19 import android.annotation.NonNull;
20 import android.annotation.SuppressLint;
21 import android.annotation.TestApi;
22 import android.content.ComponentName;
23 import android.content.Intent;
24 import android.content.res.Resources;
25 import android.os.IBinder;
26 import android.os.Parcel;
27 import android.os.ResultReceiver;
28 
29 import java.util.ArrayList;
30 
31 /**
32  * Helpers for generating the intents and related extras parameters to launch the UI activities.
33  *
34  * @hide
35  */
36 @TestApi
37 public class IntentFactory {
38     /** Generate a new launch intent to the Credential Selector UI. */
39     @NonNull
createCredentialSelectorIntent( @onNull RequestInfo requestInfo, @SuppressLint(R) @NonNull ArrayList<ProviderData> enabledProviderDataList, @SuppressLint(R) @NonNull ArrayList<DisabledProviderData> disabledProviderDataList, @NonNull ResultReceiver resultReceiver)40     public static Intent createCredentialSelectorIntent(
41             @NonNull RequestInfo requestInfo,
42             @SuppressLint("ConcreteCollection") // Concrete collection needed for marshalling.
43                     @NonNull
44                     ArrayList<ProviderData> enabledProviderDataList,
45             @SuppressLint("ConcreteCollection") // Concrete collection needed for marshalling.
46                     @NonNull
47                     ArrayList<DisabledProviderData> disabledProviderDataList,
48             @NonNull ResultReceiver resultReceiver) {
49         Intent intent = new Intent();
50         ComponentName componentName =
51                 ComponentName.unflattenFromString(
52                         Resources.getSystem()
53                                 .getString(
54                                         com.android.internal.R.string
55                                                 .config_credentialManagerDialogComponent));
56         intent.setComponent(componentName);
57 
58         intent.putParcelableArrayListExtra(
59                 ProviderData.EXTRA_ENABLED_PROVIDER_DATA_LIST, enabledProviderDataList);
60         intent.putParcelableArrayListExtra(
61                 ProviderData.EXTRA_DISABLED_PROVIDER_DATA_LIST, disabledProviderDataList);
62         intent.putExtra(RequestInfo.EXTRA_REQUEST_INFO, requestInfo);
63         intent.putExtra(
64                 Constants.EXTRA_RESULT_RECEIVER, toIpcFriendlyResultReceiver(resultReceiver));
65 
66         return intent;
67     }
68 
69     /**
70      * Creates an Intent that cancels any UI matching the given request token id.
71      *
72      * @hide
73      */
74     @NonNull
createCancelUiIntent(@onNull IBinder requestToken, boolean shouldShowCancellationUi, @NonNull String appPackageName)75     public static Intent createCancelUiIntent(@NonNull IBinder requestToken,
76             boolean shouldShowCancellationUi, @NonNull String appPackageName) {
77         Intent intent = new Intent();
78         ComponentName componentName =
79                 ComponentName.unflattenFromString(
80                         Resources.getSystem()
81                                 .getString(
82                                         com.android.internal.R.string
83                                                 .config_credentialManagerDialogComponent));
84         intent.setComponent(componentName);
85         intent.putExtra(CancelUiRequest.EXTRA_CANCEL_UI_REQUEST,
86                 new CancelUiRequest(requestToken, shouldShowCancellationUi, appPackageName));
87         return intent;
88     }
89 
90     /**
91      * Notify the UI that providers have been enabled/disabled.
92      *
93      * @hide
94      */
95     @NonNull
createProviderUpdateIntent()96     public static Intent createProviderUpdateIntent() {
97         Intent intent = new Intent();
98         ComponentName componentName =
99                 ComponentName.unflattenFromString(
100                         Resources.getSystem()
101                                 .getString(
102                                         com.android.internal.R.string
103                                                 .config_credentialManagerReceiverComponent));
104         intent.setComponent(componentName);
105         intent.setAction(Constants.CREDMAN_ENABLED_PROVIDERS_UPDATED);
106         return intent;
107     }
108 
109     /**
110      * Convert an instance of a "locally-defined" ResultReceiver to an instance of {@link
111      * android.os.ResultReceiver} itself, which the receiving process will be able to unmarshall.
112      */
toIpcFriendlyResultReceiver( T resultReceiver)113     private static <T extends ResultReceiver> ResultReceiver toIpcFriendlyResultReceiver(
114             T resultReceiver) {
115         final Parcel parcel = Parcel.obtain();
116         resultReceiver.writeToParcel(parcel, 0);
117         parcel.setDataPosition(0);
118 
119         final ResultReceiver ipcFriendly = ResultReceiver.CREATOR.createFromParcel(parcel);
120         parcel.recycle();
121 
122         return ipcFriendly;
123     }
124 
IntentFactory()125     private IntentFactory() {}
126 }
127