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