1 /* 2 * Copyright (C) 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 com.android.server.pm.pkg; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.content.pm.ApplicationInfo; 22 23 import java.util.Collections; 24 import java.util.List; 25 import java.util.Objects; 26 27 /** @hide */ 28 public class AndroidPackageSplitImpl implements AndroidPackageSplit { 29 30 @Nullable 31 private final String mName; 32 @NonNull 33 private final String mPath; 34 private final int mRevisionCode; 35 private final int mFlags; 36 @Nullable 37 private final String mClassLoaderName; 38 39 @NonNull 40 private List<AndroidPackageSplit> mDependencies = Collections.emptyList(); 41 AndroidPackageSplitImpl(@ullable String name, @NonNull String path, int revisionCode, int flags, @Nullable String classLoaderName)42 public AndroidPackageSplitImpl(@Nullable String name, @NonNull String path, int revisionCode, 43 int flags, @Nullable String classLoaderName) { 44 mName = name; 45 mPath = path; 46 mRevisionCode = revisionCode; 47 mFlags = flags; 48 mClassLoaderName = classLoaderName; 49 } 50 fillDependencies(@onNull List<AndroidPackageSplit> splits)51 public void fillDependencies(@NonNull List<AndroidPackageSplit> splits) { 52 if (!mDependencies.isEmpty()) { 53 throw new IllegalStateException("Cannot fill split dependencies more than once"); 54 } 55 mDependencies = splits; 56 } 57 58 @Nullable 59 @Override getName()60 public String getName() { 61 return mName; 62 } 63 64 @NonNull 65 @Override getPath()66 public String getPath() { 67 return mPath; 68 } 69 70 @Override getRevisionCode()71 public int getRevisionCode() { 72 return mRevisionCode; 73 } 74 75 @Override isHasCode()76 public boolean isHasCode() { 77 return (mFlags & ApplicationInfo.FLAG_HAS_CODE) != 0; 78 } 79 80 @Nullable 81 @Override getClassLoaderName()82 public String getClassLoaderName() { 83 return mClassLoaderName; 84 } 85 86 @NonNull 87 @Override getDependencies()88 public List<AndroidPackageSplit> getDependencies() { 89 return mDependencies; 90 } 91 92 @Override equals(Object o)93 public boolean equals(Object o) { 94 if (this == o) return true; 95 if (!(o instanceof AndroidPackageSplitImpl)) return false; 96 AndroidPackageSplitImpl that = (AndroidPackageSplitImpl) o; 97 var fieldsEqual = mRevisionCode == that.mRevisionCode && mFlags == that.mFlags && Objects.equals( 98 mName, that.mName) && Objects.equals(mPath, that.mPath) 99 && Objects.equals(mClassLoaderName, that.mClassLoaderName); 100 101 if (!fieldsEqual) return false; 102 if (mDependencies.size() != that.mDependencies.size()) return false; 103 104 // Should be impossible, but to avoid circular dependencies, 105 // only search 1 level deep using split name 106 for (int index = 0; index < mDependencies.size(); index++) { 107 if (!Objects.equals(mDependencies.get(index).getName(), 108 that.mDependencies.get(index).getName())) { 109 return false; 110 } 111 } 112 113 return true; 114 } 115 116 @Override hashCode()117 public int hashCode() { 118 // Should be impossible, but to avoid circular dependencies, 119 // only search 1 level deep using split name 120 var dependenciesHash = Objects.hash(mName, mPath, mRevisionCode, mFlags, mClassLoaderName); 121 for (int index = 0; index < mDependencies.size(); index++) { 122 var name = mDependencies.get(index).getName(); 123 dependenciesHash = 31 * dependenciesHash + (name == null ? 0 : name.hashCode()); 124 } 125 return dependenciesHash; 126 } 127 } 128