17340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock/* 27340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock * Copyright (C) 2014 The Android Open Source Project 37340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock * 47340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock * Licensed under the Apache License, Version 2.0 (the "License"); 57340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock * you may not use this file except in compliance with the License. 67340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock * You may obtain a copy of the License at 77340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock * 87340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock * http://www.apache.org/licenses/LICENSE-2.0 97340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock * 107340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock * Unless required by applicable law or agreed to in writing, software 117340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock * distributed under the License is distributed on an "AS IS" BASIS, 127340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock * See the License for the specific language governing permissions and 147340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock * limitations under the License. 157340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock */ 167340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock 177340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlockpackage android.service.notification; 187340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock 197340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlockimport android.annotation.SdkConstant; 20bf4e41747d138bf89c6c3fa5076a38334d3b45e1John Spurlockimport android.annotation.SystemApi; 217340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlockimport android.app.INotificationManager; 227340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlockimport android.app.Service; 237340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlockimport android.content.Context; 247340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlockimport android.content.Intent; 257340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlockimport android.net.Uri; 26e86de4c0670550a29edae77ebb9f5c8ba5631231John Spurlockimport android.os.Handler; 277340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlockimport android.os.IBinder; 28e86de4c0670550a29edae77ebb9f5c8ba5631231John Spurlockimport android.os.Message; 297340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlockimport android.os.ServiceManager; 307340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlockimport android.util.Log; 317340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock 327340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock/** 337340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock * A service that provides conditions about boolean state. 347340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock * <p>To extend this class, you must declare the service in your manifest file with 357340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock * the {@link android.Manifest.permission#BIND_CONDITION_PROVIDER_SERVICE} permission 367340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock * and include an intent filter with the {@link #SERVICE_INTERFACE} action. For example:</p> 377340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock * <pre> 387340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock * <service android:name=".MyConditionProvider" 397340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock * android:label="@string/service_name" 407340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock * android:permission="android.permission.BIND_CONDITION_PROVIDER_SERVICE"> 417340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock * <intent-filter> 427340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock * <action android:name="android.service.notification.ConditionProviderService" /> 437340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock * </intent-filter> 447340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock * </service></pre> 457340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock * 467340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock * @hide 477340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock */ 48bf4e41747d138bf89c6c3fa5076a38334d3b45e1John Spurlock@SystemApi 497340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlockpublic abstract class ConditionProviderService extends Service { 507340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock private final String TAG = ConditionProviderService.class.getSimpleName() 517340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock + "[" + getClass().getSimpleName() + "]"; 527340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock 53e86de4c0670550a29edae77ebb9f5c8ba5631231John Spurlock private final H mHandler = new H(); 54e86de4c0670550a29edae77ebb9f5c8ba5631231John Spurlock 557340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock private Provider mProvider; 567340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock private INotificationManager mNoMan; 577340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock 587340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock /** 597340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock * The {@link Intent} that must be declared as handled by the service. 607340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock */ 617340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION) 627340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock public static final String SERVICE_INTERFACE 637340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock = "android.service.notification.ConditionProviderService"; 647340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock 65e77bb36d48b6b8b5c3bb6a1195aca469bb237919John Spurlock abstract public void onConnected(); 66e77bb36d48b6b8b5c3bb6a1195aca469bb237919John Spurlock abstract public void onRequestConditions(int relevance); 67e77bb36d48b6b8b5c3bb6a1195aca469bb237919John Spurlock abstract public void onSubscribe(Uri conditionId); 68e77bb36d48b6b8b5c3bb6a1195aca469bb237919John Spurlock abstract public void onUnsubscribe(Uri conditionId); 697340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock 707340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock private final INotificationManager getNotificationInterface() { 717340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock if (mNoMan == null) { 727340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock mNoMan = INotificationManager.Stub.asInterface( 737340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock ServiceManager.getService(Context.NOTIFICATION_SERVICE)); 747340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock } 757340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock return mNoMan; 767340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock } 777340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock 781c923a386ee4d8c31cc289f8628b8fc46bf08e86John Spurlock public final void notifyCondition(Condition condition) { 791c923a386ee4d8c31cc289f8628b8fc46bf08e86John Spurlock if (condition == null) return; 801c923a386ee4d8c31cc289f8628b8fc46bf08e86John Spurlock notifyConditions(new Condition[]{ condition }); 811c923a386ee4d8c31cc289f8628b8fc46bf08e86John Spurlock } 821c923a386ee4d8c31cc289f8628b8fc46bf08e86John Spurlock 831c923a386ee4d8c31cc289f8628b8fc46bf08e86John Spurlock public final void notifyConditions(Condition... conditions) { 841c923a386ee4d8c31cc289f8628b8fc46bf08e86John Spurlock if (!isBound() || conditions == null) return; 857340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock try { 86e77bb36d48b6b8b5c3bb6a1195aca469bb237919John Spurlock getNotificationInterface().notifyConditions(getPackageName(), mProvider, conditions); 877340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock } catch (android.os.RemoteException ex) { 887340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock Log.v(TAG, "Unable to contact notification manager", ex); 897340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock } 907340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock } 917340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock 927340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock @Override 937340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock public IBinder onBind(Intent intent) { 947340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock if (mProvider == null) { 957340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock mProvider = new Provider(); 967340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock } 977340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock return mProvider; 987340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock } 997340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock 1007340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock private boolean isBound() { 1017340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock if (mProvider == null) { 1027340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock Log.w(TAG, "Condition provider service not yet bound."); 1037340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock return false; 1047340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock } 1057340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock return true; 1067340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock } 1077340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock 1087340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock private final class Provider extends IConditionProvider.Stub { 1097340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock @Override 110e77bb36d48b6b8b5c3bb6a1195aca469bb237919John Spurlock public void onConnected() { 111e86de4c0670550a29edae77ebb9f5c8ba5631231John Spurlock mHandler.obtainMessage(H.ON_CONNECTED).sendToTarget(); 1127340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock } 1137340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock 1147340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock @Override 115e77bb36d48b6b8b5c3bb6a1195aca469bb237919John Spurlock public void onRequestConditions(int relevance) { 116e86de4c0670550a29edae77ebb9f5c8ba5631231John Spurlock mHandler.obtainMessage(H.ON_REQUEST_CONDITIONS, relevance, 0).sendToTarget(); 1177340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock } 1187340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock 1197340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock @Override 120e77bb36d48b6b8b5c3bb6a1195aca469bb237919John Spurlock public void onSubscribe(Uri conditionId) { 121e86de4c0670550a29edae77ebb9f5c8ba5631231John Spurlock mHandler.obtainMessage(H.ON_SUBSCRIBE, conditionId).sendToTarget(); 1227340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock } 1237340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock 1247340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock @Override 125e77bb36d48b6b8b5c3bb6a1195aca469bb237919John Spurlock public void onUnsubscribe(Uri conditionId) { 126e86de4c0670550a29edae77ebb9f5c8ba5631231John Spurlock mHandler.obtainMessage(H.ON_UNSUBSCRIBE, conditionId).sendToTarget(); 127e86de4c0670550a29edae77ebb9f5c8ba5631231John Spurlock } 128e86de4c0670550a29edae77ebb9f5c8ba5631231John Spurlock } 129e86de4c0670550a29edae77ebb9f5c8ba5631231John Spurlock 130e86de4c0670550a29edae77ebb9f5c8ba5631231John Spurlock private final class H extends Handler { 131e86de4c0670550a29edae77ebb9f5c8ba5631231John Spurlock private static final int ON_CONNECTED = 1; 132e86de4c0670550a29edae77ebb9f5c8ba5631231John Spurlock private static final int ON_REQUEST_CONDITIONS = 2; 133e86de4c0670550a29edae77ebb9f5c8ba5631231John Spurlock private static final int ON_SUBSCRIBE = 3; 134e86de4c0670550a29edae77ebb9f5c8ba5631231John Spurlock private static final int ON_UNSUBSCRIBE = 4; 135e86de4c0670550a29edae77ebb9f5c8ba5631231John Spurlock 136e86de4c0670550a29edae77ebb9f5c8ba5631231John Spurlock @Override 137e86de4c0670550a29edae77ebb9f5c8ba5631231John Spurlock public void handleMessage(Message msg) { 138e86de4c0670550a29edae77ebb9f5c8ba5631231John Spurlock String name = null; 1397340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock try { 140e86de4c0670550a29edae77ebb9f5c8ba5631231John Spurlock switch(msg.what) { 141e86de4c0670550a29edae77ebb9f5c8ba5631231John Spurlock case ON_CONNECTED: 142e86de4c0670550a29edae77ebb9f5c8ba5631231John Spurlock name = "onConnected"; 143e86de4c0670550a29edae77ebb9f5c8ba5631231John Spurlock onConnected(); 144e86de4c0670550a29edae77ebb9f5c8ba5631231John Spurlock break; 145e86de4c0670550a29edae77ebb9f5c8ba5631231John Spurlock case ON_REQUEST_CONDITIONS: 146e86de4c0670550a29edae77ebb9f5c8ba5631231John Spurlock name = "onRequestConditions"; 147e86de4c0670550a29edae77ebb9f5c8ba5631231John Spurlock onRequestConditions(msg.arg1); 148e86de4c0670550a29edae77ebb9f5c8ba5631231John Spurlock break; 149e86de4c0670550a29edae77ebb9f5c8ba5631231John Spurlock case ON_SUBSCRIBE: 150e86de4c0670550a29edae77ebb9f5c8ba5631231John Spurlock name = "onSubscribe"; 151e86de4c0670550a29edae77ebb9f5c8ba5631231John Spurlock onSubscribe((Uri)msg.obj); 152e86de4c0670550a29edae77ebb9f5c8ba5631231John Spurlock break; 153e86de4c0670550a29edae77ebb9f5c8ba5631231John Spurlock case ON_UNSUBSCRIBE: 154e86de4c0670550a29edae77ebb9f5c8ba5631231John Spurlock name = "onUnsubscribe"; 155e86de4c0670550a29edae77ebb9f5c8ba5631231John Spurlock onUnsubscribe((Uri)msg.obj); 156e86de4c0670550a29edae77ebb9f5c8ba5631231John Spurlock break; 157e86de4c0670550a29edae77ebb9f5c8ba5631231John Spurlock } 1587340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock } catch (Throwable t) { 159e86de4c0670550a29edae77ebb9f5c8ba5631231John Spurlock Log.w(TAG, "Error running " + name, t); 1607340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock } 1617340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock } 1627340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock } 1637340fc8665ae3f9f1978f42aa0e5e1da85036158John Spurlock} 164