• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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 com.android.permissioncontroller.role.model;
18 
19 import android.content.ComponentName;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.content.IntentFilter;
23 import android.content.pm.PackageManager;
24 import android.content.pm.ResolveInfo;
25 
26 import androidx.annotation.NonNull;
27 
28 import java.util.ArrayList;
29 import java.util.List;
30 import java.util.Objects;
31 
32 /**
33  * Specifies a preferred {@code Activity} configuration to be configured by a {@link Role}.
34  */
35 public class PreferredActivity {
36 
37     /**
38      * The specification of the {@code Activity} to be preferred.
39      */
40     @NonNull
41     private final RequiredActivity mActivity;
42 
43     /**
44      * The list of {@code IntentFilter} specifications to be configured to prefer this
45      * {@code Activity}.
46      */
47     @NonNull
48     private final List<IntentFilterData> mIntentFilterDatas;
49 
PreferredActivity(@onNull RequiredActivity activity, @NonNull List<IntentFilterData> intentFilterDatas)50     public PreferredActivity(@NonNull RequiredActivity activity,
51             @NonNull List<IntentFilterData> intentFilterDatas) {
52         mActivity = activity;
53         mIntentFilterDatas = intentFilterDatas;
54     }
55 
56     @NonNull
getActivity()57     public RequiredActivity getActivity() {
58         return mActivity;
59     }
60 
61     @NonNull
getIntentFilterDatas()62     public List<IntentFilterData> getIntentFilterDatas() {
63         return mIntentFilterDatas;
64     }
65 
66     /**
67      * Configure this preferred activity specification for an application.
68      *
69      * @param packageName the package name of the application
70      * @param context the {@code Context} to retrieve system services
71      */
configure(@onNull String packageName, @NonNull Context context)72     public void configure(@NonNull String packageName, @NonNull Context context) {
73         ComponentName packageActivity = mActivity.getQualifyingComponentForPackage(
74                 packageName, context);
75         if (packageActivity == null) {
76             // We might be running into some race condition here, but we can't do anything about it.
77             // This should be handled by a future reconciliation started by the package change.
78             return;
79         }
80 
81         PackageManager packageManager = context.getPackageManager();
82         int intentFilterDatasSize = mIntentFilterDatas.size();
83         for (int i = 0; i < intentFilterDatasSize; i++) {
84             IntentFilterData intentFilterData = mIntentFilterDatas.get(i);
85 
86             IntentFilter intentFilter = intentFilterData.createIntentFilter();
87             intentFilter.addCategory(Intent.CATEGORY_DEFAULT);
88 
89             // PackageManager.replacePreferredActivity() expects filter to have no data authorities,
90             // paths, or types; and at most one scheme.
91             int match = intentFilterData.getDataScheme() != null
92                     ? IntentFilter.MATCH_CATEGORY_SCHEME : IntentFilter.MATCH_CATEGORY_EMPTY;
93 
94             Intent intent = intentFilterData.createIntent();
95             List<ResolveInfo> resolveInfos = packageManager.queryIntentActivities(intent,
96                     PackageManager.MATCH_DIRECT_BOOT_AWARE
97                             | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
98                             | PackageManager.MATCH_DEFAULT_ONLY);
99             List<ComponentName> set = new ArrayList<>();
100             int resolveInfosSize = resolveInfos.size();
101             for (int resolveInfosIndex = 0; resolveInfosIndex < resolveInfosSize;
102                     resolveInfosIndex++) {
103                 ResolveInfo resolveInfo = resolveInfos.get(resolveInfosIndex);
104 
105                 ComponentName componentName = new ComponentName(
106                         resolveInfo.activityInfo.packageName, resolveInfo.activityInfo.name);
107                 set.add(componentName);
108             }
109 
110             packageManager.replacePreferredActivity(intentFilter, match, set, packageActivity);
111         }
112     }
113 
114     @Override
toString()115     public String toString() {
116         return "PreferredActivity{"
117                 + "mActivity=" + mActivity
118                 + ", mIntentFilterDatas=" + mIntentFilterDatas
119                 + '}';
120     }
121 
122     @Override
equals(Object object)123     public boolean equals(Object object) {
124         if (this == object) {
125             return true;
126         }
127         if (object == null || getClass() != object.getClass()) {
128             return false;
129         }
130         PreferredActivity that = (PreferredActivity) object;
131         return Objects.equals(mActivity, that.mActivity)
132                 && Objects.equals(mIntentFilterDatas, that.mIntentFilterDatas);
133     }
134 
135     @Override
hashCode()136     public int hashCode() {
137         return Objects.hash(mActivity, mIntentFilterDatas);
138     }
139 }
140