ConditionProviders.java revision e77bb36d48b6b8b5c3bb6a1195aca469bb237919
1/** 2 * Copyright (c) 2014, 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 17package com.android.server.notification; 18 19import android.content.Context; 20import android.net.Uri; 21import android.os.Handler; 22import android.os.IBinder; 23import android.os.IInterface; 24import android.os.RemoteException; 25import android.provider.Settings; 26import android.service.notification.Condition; 27import android.service.notification.ConditionProviderService; 28import android.service.notification.IConditionListener; 29import android.service.notification.IConditionProvider; 30import android.util.ArrayMap; 31import android.util.Slog; 32 33import com.android.internal.R; 34 35import libcore.util.Objects; 36 37import java.io.PrintWriter; 38import java.util.Arrays; 39 40public class ConditionProviders extends ManagedServices { 41 42 private final ZenModeHelper mZenModeHelper; 43 private final ArrayMap<IBinder, IConditionListener> mListeners 44 = new ArrayMap<IBinder, IConditionListener>(); 45 private final ArrayMap<Uri, ManagedServiceInfo> mConditions 46 = new ArrayMap<Uri, ManagedServiceInfo>(); 47 48 private Uri mCurrentConditionId; 49 50 public ConditionProviders(Context context, Handler handler, 51 UserProfiles userProfiles, ZenModeHelper zenModeHelper) { 52 super(context, handler, new Object(), userProfiles); 53 mZenModeHelper = zenModeHelper; 54 } 55 56 @Override 57 protected Config getConfig() { 58 Config c = new Config(); 59 c.caption = "condition provider"; 60 c.serviceInterface = ConditionProviderService.SERVICE_INTERFACE; 61 c.secureSettingName = Settings.Secure.ENABLED_CONDITION_PROVIDERS; 62 c.bindPermission = android.Manifest.permission.BIND_CONDITION_PROVIDER_SERVICE; 63 c.settingsAction = Settings.ACTION_CONDITION_PROVIDER_SETTINGS; 64 c.clientLabel = R.string.condition_provider_service_binding_label; 65 return c; 66 } 67 68 @Override 69 public void dump(PrintWriter pw) { 70 super.dump(pw); 71 synchronized(mMutex) { 72 pw.print(" mCurrentConditionId="); pw.println(mCurrentConditionId); 73 pw.print(" mListeners("); pw.print(mListeners.size()); pw.println("):"); 74 for (int i = 0; i < mListeners.size(); i++) { 75 pw.print(" "); pw.println(mListeners.keyAt(i)); 76 } 77 pw.print(" mConditions("); pw.print(mConditions.size()); pw.println("):"); 78 for (int i = 0; i < mConditions.size(); i++) { 79 pw.print(" "); pw.print(mConditions.keyAt(i)); 80 final ManagedServiceInfo info = mConditions.valueAt(i); 81 pw.print(" -> "); pw.print(info.component); 82 if (!mServices.contains(info)) { 83 pw.print(" (orphan)"); 84 } 85 pw.println(); 86 } 87 } 88 } 89 90 @Override 91 protected IInterface asInterface(IBinder binder) { 92 return IConditionProvider.Stub.asInterface(binder); 93 } 94 95 @Override 96 protected void onServiceAdded(IInterface service) { 97 Slog.d(TAG, "onServiceAdded " + service); 98 final IConditionProvider provider = (IConditionProvider) service; 99 try { 100 provider.onConnected(); 101 } catch (RemoteException e) { 102 // we tried 103 } 104 } 105 106 @Override 107 protected void onServiceRemovedLocked(ManagedServiceInfo removed) { 108 if (removed == null) return; 109 for (int i = mConditions.size() - 1; i >= 0; i--) { 110 if (removed.equals(mConditions.valueAt(i))) { 111 mConditions.removeAt(i); 112 } 113 } 114 } 115 116 public ManagedServiceInfo checkServiceToken(IConditionProvider provider) { 117 synchronized(mMutex) { 118 return checkServiceTokenLocked(provider); 119 } 120 } 121 122 public void requestZenModeConditions(IConditionListener callback, boolean requested) { 123 synchronized(mMutex) { 124 if (DEBUG) Slog.d(TAG, "requestZenModeConditions callback=" + callback 125 + " requested=" + requested); 126 if (callback == null) return; 127 if (requested) { 128 mListeners.put(callback.asBinder(), callback); 129 requestConditionsLocked(Condition.FLAG_RELEVANT_NOW); 130 } else { 131 mListeners.remove(callback.asBinder()); 132 if (mListeners.isEmpty()) { 133 requestConditionsLocked(0); 134 } 135 } 136 } 137 } 138 139 public void notifyConditions(String pkg, ManagedServiceInfo info, Condition[] conditions) { 140 synchronized(mMutex) { 141 if (DEBUG) Slog.d(TAG, "notifyConditions pkg=" + pkg + " info=" + info + " conditions=" 142 + (conditions == null ? null : Arrays.asList(conditions))); 143 if (conditions == null || conditions.length == 0) return; 144 final int N = conditions.length; 145 boolean valid = true; 146 for (int i = 0; i < N; i++) { 147 final Uri id = conditions[i].id; 148 if (!Condition.isValidId(id, pkg)) { 149 Slog.w(TAG, "Ignoring conditions from " + pkg + " for invalid id: " + id); 150 valid = false; 151 } 152 } 153 if (!valid) return; 154 155 for (int i = 0; i < N; i++) { 156 mConditions.put(conditions[i].id, info); 157 } 158 for (IConditionListener listener : mListeners.values()) { 159 try { 160 listener.onConditionsReceived(conditions); 161 } catch (RemoteException e) { 162 Slog.w(TAG, "Error sending conditions to listener " + listener, e); 163 } 164 } 165 if (mCurrentConditionId != null) { 166 for (int i = 0; i < N; i++) { 167 final Condition c = conditions[i]; 168 if (!c.id.equals(mCurrentConditionId)) continue; 169 if (c.state == Condition.STATE_TRUE || c.state == Condition.STATE_ERROR) { 170 triggerExitLocked(c.state == Condition.STATE_ERROR); 171 return; 172 } 173 } 174 } 175 } 176 } 177 178 private void triggerExitLocked(boolean error) { 179 if (error) { 180 Slog.w(TAG, "Zen mode exit condition failed"); 181 } else if (DEBUG) { 182 Slog.d(TAG, "Zen mode exit condition triggered"); 183 } 184 mZenModeHelper.setZenMode(Settings.Global.ZEN_MODE_OFF); 185 unsubscribeLocked(mCurrentConditionId); 186 mCurrentConditionId = null; 187 } 188 189 public void setZenModeCondition(Uri conditionId) { 190 synchronized(mMutex) { 191 if (DEBUG) Slog.d(TAG, "setZenModeCondition " + conditionId); 192 if (Objects.equal(mCurrentConditionId, conditionId)) return; 193 194 if (mCurrentConditionId != null) { 195 unsubscribeLocked(mCurrentConditionId); 196 } 197 if (conditionId != null) { 198 final ManagedServiceInfo info = mConditions.get(conditionId); 199 final IConditionProvider provider = provider(info); 200 if (provider == null) return; 201 try { 202 provider.onSubscribe(conditionId); 203 } catch (RemoteException e) { 204 Slog.w(TAG, "Error subscribing to " + conditionId 205 + " from " + info.component, e); 206 } 207 } 208 mCurrentConditionId = conditionId; 209 } 210 } 211 212 private void unsubscribeLocked(Uri conditionId) { 213 final ManagedServiceInfo info = mConditions.get(mCurrentConditionId); 214 final IConditionProvider provider = provider(info); 215 if (provider == null) return; 216 try { 217 provider.onUnsubscribe(conditionId); 218 } catch (RemoteException e) { 219 Slog.w(TAG, "Error unsubscribing to " + conditionId + " from " + info.component, e); 220 } 221 } 222 223 private static IConditionProvider provider(ManagedServiceInfo info) { 224 return info == null ? null : (IConditionProvider) info.service; 225 } 226 227 private void requestConditionsLocked(int flags) { 228 for (ManagedServiceInfo info : mServices) { 229 final IConditionProvider provider = provider(info); 230 if (provider == null) continue; 231 try { 232 provider.onRequestConditions(flags); 233 } catch (RemoteException e) { 234 Slog.w(TAG, "Error requesting conditions from " + info.component, e); 235 } 236 } 237 } 238} 239