1 /* 2 * Copyright (C) 2020 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.content.pm.parsing.component; 18 19 import android.annotation.Nullable; 20 import android.content.IntentFilter; 21 import android.os.Parcel; 22 import android.util.Pair; 23 24 import com.android.internal.util.DataClass; 25 import com.android.internal.util.Parcelling; 26 27 import java.util.ArrayList; 28 import java.util.List; 29 30 /** @hide **/ 31 public final class ParsedIntentInfo extends IntentFilter { 32 33 public static final Parceler PARCELER = new Parceler(); 34 35 public static class Parceler implements Parcelling<ParsedIntentInfo> { 36 37 @Override parcel(ParsedIntentInfo item, Parcel dest, int parcelFlags)38 public void parcel(ParsedIntentInfo item, Parcel dest, int parcelFlags) { 39 item.writeIntentInfoToParcel(dest, parcelFlags); 40 } 41 42 @Override unparcel(Parcel source)43 public ParsedIntentInfo unparcel(Parcel source) { 44 return new ParsedIntentInfo(source); 45 } 46 } 47 48 public static class ListParceler implements Parcelling<List<ParsedIntentInfo>> { 49 50 /** 51 * <p> 52 * Implementation note: The serialized form for the intent list also contains the name 53 * of the concrete class that's stored in the list, and assumes that every element of the 54 * list is of the same type. This is very similar to the original parcelable mechanism. 55 * We cannot use that directly because IntentInfo extends IntentFilter, which is parcelable 56 * and is public API. It also declares Parcelable related methods as final which means 57 * we can't extend them. The approach of using composition instead of inheritance leads to 58 * a large set of cascading changes in the PackageManagerService, which seem undesirable. 59 * 60 * <p> 61 * <b>WARNING: </b> The list of objects returned by this function might need to be fixed up 62 * to make sure their owner fields are consistent. See {@code fixupOwner}. 63 */ 64 @Override parcel(List<ParsedIntentInfo> item, Parcel dest, int parcelFlags)65 public void parcel(List<ParsedIntentInfo> item, Parcel dest, int parcelFlags) { 66 if (item == null) { 67 dest.writeInt(-1); 68 return; 69 } 70 71 final int size = item.size(); 72 dest.writeInt(size); 73 74 for (int index = 0; index < size; index++) { 75 PARCELER.parcel(item.get(index), dest, parcelFlags); 76 } 77 } 78 79 @Override unparcel(Parcel source)80 public List<ParsedIntentInfo> unparcel(Parcel source) { 81 int size = source.readInt(); 82 if (size == -1) { 83 return null; 84 } 85 86 if (size == 0) { 87 return new ArrayList<>(0); 88 } 89 90 final ArrayList<ParsedIntentInfo> intentsList = new ArrayList<>(size); 91 for (int i = 0; i < size; ++i) { 92 intentsList.add(PARCELER.unparcel(source)); 93 } 94 95 return intentsList; 96 } 97 } 98 99 public static class StringPairListParceler implements Parcelling<List<Pair<String, ParsedIntentInfo>>> { 100 101 @Override parcel(List<Pair<String, ParsedIntentInfo>> item, Parcel dest, int parcelFlags)102 public void parcel(List<Pair<String, ParsedIntentInfo>> item, Parcel dest, 103 int parcelFlags) { 104 if (item == null) { 105 dest.writeInt(-1); 106 return; 107 } 108 109 final int size = item.size(); 110 dest.writeInt(size); 111 112 for (int index = 0; index < size; index++) { 113 Pair<String, ParsedIntentInfo> pair = item.get(index); 114 dest.writeString(pair.first); 115 PARCELER.parcel(pair.second, dest, parcelFlags); 116 } 117 } 118 119 @Override unparcel(Parcel source)120 public List<Pair<String, ParsedIntentInfo>> unparcel(Parcel source) { 121 int size = source.readInt(); 122 if (size == -1) { 123 return null; 124 } 125 126 if (size == 0) { 127 return new ArrayList<>(0); 128 } 129 130 final List<Pair<String, ParsedIntentInfo>> list = new ArrayList<>(size); 131 for (int i = 0; i < size; ++i) { 132 list.add(Pair.create(source.readString(), PARCELER.unparcel(source))); 133 } 134 135 return list; 136 } 137 } 138 139 boolean hasDefault; 140 int labelRes; 141 @Nullable 142 CharSequence nonLocalizedLabel; 143 int icon; 144 ParsedIntentInfo()145 public ParsedIntentInfo() { 146 } 147 ParsedIntentInfo(Parcel in)148 public ParsedIntentInfo(Parcel in) { 149 super(in); 150 hasDefault = in.readBoolean(); 151 labelRes = in.readInt(); 152 nonLocalizedLabel = in.readCharSequence(); 153 icon = in.readInt(); 154 } 155 writeIntentInfoToParcel(Parcel dest, int flags)156 public void writeIntentInfoToParcel(Parcel dest, int flags) { 157 super.writeToParcel(dest, flags); 158 dest.writeBoolean(hasDefault); 159 dest.writeInt(labelRes); 160 dest.writeCharSequence(nonLocalizedLabel); 161 dest.writeInt(icon); 162 } 163 toString()164 public String toString() { 165 return "ProviderIntentInfo{" 166 + Integer.toHexString(System.identityHashCode(this)) 167 + '}'; 168 } 169 isHasDefault()170 public boolean isHasDefault() { 171 return hasDefault; 172 } 173 getLabelRes()174 public int getLabelRes() { 175 return labelRes; 176 } 177 178 @Nullable getNonLocalizedLabel()179 public CharSequence getNonLocalizedLabel() { 180 return nonLocalizedLabel; 181 } 182 getIcon()183 public int getIcon() { 184 return icon; 185 } 186 } 187