Home | History | Annotate | Download | only in notification
      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 
     17 package android.service.notification;
     18 
     19 import android.annotation.SdkConstant;
     20 import android.annotation.SystemApi;
     21 import android.app.INotificationManager;
     22 import android.app.Service;
     23 import android.content.Context;
     24 import android.content.Intent;
     25 import android.net.Uri;
     26 import android.os.Handler;
     27 import android.os.IBinder;
     28 import android.os.Message;
     29 import android.os.ServiceManager;
     30 import android.util.Log;
     31 
     32 /**
     33  * A service that provides conditions about boolean state.
     34  * <p>To extend this class, you must declare the service in your manifest file with
     35  * the {@link android.Manifest.permission#BIND_CONDITION_PROVIDER_SERVICE} permission
     36  * and include an intent filter with the {@link #SERVICE_INTERFACE} action. For example:</p>
     37  * <pre>
     38  * &lt;service android:name=".MyConditionProvider"
     39  *          android:label="&#64;string/service_name"
     40  *          android:permission="android.permission.BIND_CONDITION_PROVIDER_SERVICE">
     41  *     &lt;intent-filter>
     42  *         &lt;action android:name="android.service.notification.ConditionProviderService" />
     43  *     &lt;/intent-filter>
     44  * &lt;/service></pre>
     45  *
     46  * @hide
     47  */
     48 @SystemApi
     49 public abstract class ConditionProviderService extends Service {
     50     private final String TAG = ConditionProviderService.class.getSimpleName()
     51             + "[" + getClass().getSimpleName() + "]";
     52 
     53     private final H mHandler = new H();
     54 
     55     private Provider mProvider;
     56     private INotificationManager mNoMan;
     57 
     58     /**
     59      * The {@link Intent} that must be declared as handled by the service.
     60      */
     61     @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
     62     public static final String SERVICE_INTERFACE
     63             = "android.service.notification.ConditionProviderService";
     64 
     65     abstract public void onConnected();
     66     abstract public void onRequestConditions(int relevance);
     67     abstract public void onSubscribe(Uri conditionId);
     68     abstract public void onUnsubscribe(Uri conditionId);
     69 
     70     private final INotificationManager getNotificationInterface() {
     71         if (mNoMan == null) {
     72             mNoMan = INotificationManager.Stub.asInterface(
     73                     ServiceManager.getService(Context.NOTIFICATION_SERVICE));
     74         }
     75         return mNoMan;
     76     }
     77 
     78     public final void notifyCondition(Condition condition) {
     79         if (condition == null) return;
     80         notifyConditions(new Condition[]{ condition });
     81     }
     82 
     83     public final void notifyConditions(Condition... conditions) {
     84         if (!isBound() || conditions == null) return;
     85         try {
     86             getNotificationInterface().notifyConditions(getPackageName(), mProvider, conditions);
     87         } catch (android.os.RemoteException ex) {
     88             Log.v(TAG, "Unable to contact notification manager", ex);
     89         }
     90     }
     91 
     92     @Override
     93     public IBinder onBind(Intent intent) {
     94         if (mProvider == null) {
     95             mProvider = new Provider();
     96         }
     97         return mProvider;
     98     }
     99 
    100     private boolean isBound() {
    101         if (mProvider == null) {
    102             Log.w(TAG, "Condition provider service not yet bound.");
    103             return false;
    104         }
    105         return true;
    106     }
    107 
    108     private final class Provider extends IConditionProvider.Stub {
    109         @Override
    110         public void onConnected() {
    111             mHandler.obtainMessage(H.ON_CONNECTED).sendToTarget();
    112         }
    113 
    114         @Override
    115         public void onRequestConditions(int relevance) {
    116             mHandler.obtainMessage(H.ON_REQUEST_CONDITIONS, relevance, 0).sendToTarget();
    117         }
    118 
    119         @Override
    120         public void onSubscribe(Uri conditionId) {
    121             mHandler.obtainMessage(H.ON_SUBSCRIBE, conditionId).sendToTarget();
    122         }
    123 
    124         @Override
    125         public void onUnsubscribe(Uri conditionId) {
    126             mHandler.obtainMessage(H.ON_UNSUBSCRIBE, conditionId).sendToTarget();
    127         }
    128     }
    129 
    130     private final class H extends Handler {
    131         private static final int ON_CONNECTED = 1;
    132         private static final int ON_REQUEST_CONDITIONS = 2;
    133         private static final int ON_SUBSCRIBE = 3;
    134         private static final int ON_UNSUBSCRIBE = 4;
    135 
    136         @Override
    137         public void handleMessage(Message msg) {
    138             String name = null;
    139             try {
    140                 switch(msg.what) {
    141                     case ON_CONNECTED:
    142                         name = "onConnected";
    143                         onConnected();
    144                         break;
    145                     case ON_REQUEST_CONDITIONS:
    146                         name = "onRequestConditions";
    147                         onRequestConditions(msg.arg1);
    148                         break;
    149                     case ON_SUBSCRIBE:
    150                         name = "onSubscribe";
    151                         onSubscribe((Uri)msg.obj);
    152                         break;
    153                     case ON_UNSUBSCRIBE:
    154                         name = "onUnsubscribe";
    155                         onUnsubscribe((Uri)msg.obj);
    156                         break;
    157                 }
    158             } catch (Throwable t) {
    159                 Log.w(TAG, "Error running " + name, t);
    160             }
    161         }
    162     }
    163 }
    164