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 com.android.server.pm; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.content.IntentFilter; 22 23 import com.android.server.IntentResolver; 24 import com.android.server.pm.snapshot.PackageDataSnapshot; 25 import com.android.server.utils.Snappable; 26 import com.android.server.utils.Watchable; 27 import com.android.server.utils.WatchableImpl; 28 import com.android.server.utils.Watcher; 29 30 import java.util.ArrayList; 31 import java.util.Collections; 32 import java.util.Comparator; 33 import java.util.List; 34 35 /** 36 * A watched {@link IntentResolver}. The parameters are inherited from the superclass. 37 * @param <F> The filter type 38 * @param <R> The resolver type. 39 * {@hide} 40 */ 41 public abstract class WatchedIntentResolver<F extends WatchedIntentFilter, 42 R extends WatchedIntentFilter> 43 extends IntentResolver<F, R> 44 implements Watchable, Snappable { 45 46 /** 47 * Watchable machinery 48 */ 49 private final Watchable mWatchable = new WatchableImpl(); 50 51 /** 52 * Register an observer to receive change notifications. 53 * @param observer The observer to register. 54 */ 55 @Override registerObserver(@onNull Watcher observer)56 public void registerObserver(@NonNull Watcher observer) { 57 mWatchable.registerObserver(observer); 58 } 59 60 /** 61 * Unregister the observer, which will no longer receive change notifications. 62 * @param observer The observer to unregister. 63 */ 64 @Override unregisterObserver(@onNull Watcher observer)65 public void unregisterObserver(@NonNull Watcher observer) { 66 mWatchable.unregisterObserver(observer); 67 } 68 69 /** 70 * Return true if the {@link Watcher) is a registered observer. 71 * @param observer A {@link Watcher} that might be registered 72 * @return true if the observer is registered with this {@link Watchable}. 73 */ 74 @Override isRegisteredObserver(@onNull Watcher observer)75 public boolean isRegisteredObserver(@NonNull Watcher observer) { 76 return mWatchable.isRegisteredObserver(observer); 77 } 78 79 /** 80 * Notify listeners that the object has changd. The argument is a hint as to the 81 * source of the change. 82 * @param what The attribute or sub-object that changed, if not null. 83 */ 84 @Override dispatchChange(@ullable Watchable what)85 public void dispatchChange(@Nullable Watchable what) { 86 mWatchable.dispatchChange(what); 87 } 88 89 private final Watcher mWatcher = new Watcher() { 90 @Override 91 public void onChange(@Nullable Watchable what) { 92 dispatchChange(what); 93 } 94 }; 95 96 /** 97 * Notify listeners that this object has changed. 98 */ onChanged()99 protected void onChanged() { 100 dispatchChange(this); 101 } 102 103 @Override addFilter(@ullable PackageDataSnapshot snapshot, F f)104 public void addFilter(@Nullable PackageDataSnapshot snapshot, F f) { 105 super.addFilter(snapshot, f); 106 f.registerObserver(mWatcher); 107 onChanged(); 108 } 109 110 @Override removeFilter(F f)111 public void removeFilter(F f) { 112 f.unregisterObserver(mWatcher); 113 super.removeFilter(f); 114 onChanged(); 115 } 116 117 @Override removeFilterInternal(F f)118 protected void removeFilterInternal(F f) { 119 f.unregisterObserver(mWatcher); 120 super.removeFilterInternal(f); 121 onChanged(); 122 } 123 124 // Sorts a List of IntentFilter objects into descending priority order. 125 @SuppressWarnings("rawtypes") 126 private static final Comparator<WatchedIntentFilter> sResolvePrioritySorter = 127 new Comparator<>() { 128 public int compare(WatchedIntentFilter o1, WatchedIntentFilter o2) { 129 final int q1 = o1.getPriority(); 130 final int q2 = o2.getPriority(); 131 return (q1 > q2) ? -1 : ((q1 < q2) ? 1 : 0); 132 } 133 }; 134 135 @Override 136 @SuppressWarnings("unchecked") sortResults(List<R> results)137 protected void sortResults(List<R> results) { 138 Collections.sort(results, sResolvePrioritySorter); 139 } 140 141 /** 142 * @see IntentResolver#findFilters(IntentFilter) 143 */ findFilters(WatchedIntentFilter matching)144 public ArrayList<F> findFilters(WatchedIntentFilter matching) { 145 return super.findFilters(matching.getIntentFilter()); 146 } 147 148 // Make <this> a copy of <orig>. The presumption is that <this> is empty but all 149 // arrays are cleared out explicitly, just to be sure. copyFrom(WatchedIntentResolver orig)150 protected void copyFrom(WatchedIntentResolver orig) { 151 super.copyFrom(orig); 152 } 153 } 154