Notification呼吸灯设置流程浅析

分析平台Android4.4,

Android 系统架构中:一个manager类对应一个aidl接口,一个manager对应一个底层的服务,notification也是这个架构。

 1.一个普通apk调用notification实现呼吸灯灯效,主要是通过在Notification里面设置效果参数传入NotificationManagernotify方法 ,通过aidl接口转换传入NotificationManagerService

 需要设置如下代码:

1.1:获取NotificationManager:

NotificationManager mNotificationManager=(NotificationManager)this.getSystemService(NOTIFICATION_SERVICE);

1.2:定义一个Notification:

  Notification  mNotification=new Notification();

1.3:设置Notification的各种属性:

//设置通知在状态栏显示的图标

mNotification.icon=R.drawable.icon;          

//当我们点击通知时显示的内容

mNotification.tickerText="Button1通知内容.....";                           

//通知时发出的默认声音

mNotification.defaults=Notification.DEFAULT_SOUND;

Android支持三色灯提醒,可以根据不同的场景选择点亮不同颜色的灯。需要注意的是,只有设置Notification的标志位为FLAG_SHOW_LIGHTS,才能支持三色灯提醒。创建三色灯提醒的Notification示例如下:

mNotification.flags |= Notification.FLAG_SHOW_LIGHTS;

提醒标志位(

Notification支持FLAG_SHOW_LIGHTSFLAG_ONGOING_EVENTFLAG_INSISTENTFLAG_ ONLY_ALERT_ONCEFLAG_AUTO_CANCELFLAG_NO_CLEARFLAG_FOREGROUND_SERVICE等多种提醒标志位,其含义分别如下:

FLAG_SHOW_LIGHTS //三色灯提醒

FLAG_ONGOING_EVENT //发起事件

FLAG_INSISTENT //振铃音将持续到Notification取消或Notification窗口打开

FLAG_ONLY_ALERT_ONCE //发起Notification后,振铃音或振动均只执行一次

FLAG_AUTO_CANCEL //用户单击后自动消失

FLAG_NO_CLEAR //只有全部清除时,Notification才会清除

FLAG_FOREGROUND_SERVICE //表示正运行的服务)

mNotification.ledARGB = 0xff0000f;//Led颜色

mNotification.ledOnMS = 300;//led亮的时间

mNotification.ledOffMS = 300;;//led灭的时间

//设置通知显示的参数

PendingIntent m_PendingIntent=PendingIntent.getActivity(NotificationDemo.this, 0, m_Intent, 0);

mNotification.setLatestEventInfo(NotificationDemo.this, "Button1", "Button1通知",m_PendingIntent );

//开始执行这个通知

mNotificationManager.notify(0,mNotification);

将设置好的参数信息打包到m_Notification中传入NotificationManager继续处理


2.frameworks/base/core/java/android/app/NotificationManager.java

    static public INotificationManager getService()

    {

        if (sService != null) {

            return sService;

        }

        IBinder b = ServiceManager.getService("notification");

        sService = INotificationManager.Stub.asInterface(b);

        return sService;

}

 

  public void notify(String tag, int id, Notification notification)

    {

        int[] idOut = new int[1];

        INotificationManager service = getService();

        String pkg = mContext.getPackageName();

        if (notification.sound != null) {

            notification.sound = notification.sound.getCanonicalUri();

            if (StrictMode.vmFileUriExposureEnabled()) {

                notification.sound.checkFileUriExposed("Notification.sound");

            }

        }

        if (localLOGV) Log.v(TAG, pkg + ": notify(" + id + ", " + notification + ")");

        Notification stripped = notification.clone();

        Builder.stripForDelivery(stripped);

        try {

            service.enqueueNotificationWithTag(pkg, mContext.getOpPackageName(), tag, id,

                   stripped, idOut, UserHandle.myUserId());

            if (id != idOut[0]) {

                Log.w(TAG, "notify: id corrupted: sent " + id + ", got back " + idOut[0]);

            }

        } catch (RemoteException e) {

        }

    }

通过aidl接口调用到  NotificationManagerService中的enqueueNotificationWithTag方法中,enqueue说明notification的内部维护着一个队列,接收不同apk发送的通知请求。

3.frameworks/base/services/core/java/com/android/server/notification/NotificationManagerService.java中实现了灯效,亮灭时长灯的逻辑控制。

其中定义了MAX_PACKAGE_NOTIFICATIONS = 50,最大可以接收五十个通知

        @Override

        public void enqueueNotificationWithTag(String pkg, String opPkg, String tag, int id,

                Notification notification, int[] idOut, int userId) throws RemoteException {

            enqueueNotificationInternal(pkg, opPkg, Binder.getCallingUid(),

                    Binder.getCallingPid(), tag, id,notification, idOut, userId);

        }

  void enqueueNotificationInternal(final String pkg, final String opPkg, final int callingUid,

            final int callingPid, final String tag, final int id, final Notificationnotification,

            int[] idOut, int incomingUserId) {……….

…………………………..

………………….

}在这里对mNotificationList通知消息队列各条通知的优先级,声音进行了相关操作

 

最后进入updateLightsLocked在其中将设置好的灯效颜色,类型,时间长短写入LightsService

      mNotificationLight.setFlashing(ledARGB, LightsService.LIGHT_FLASH_TIMED,

                        ledOnMS, ledOffMS);

 

4.frameworks/base/services/core/java/com/android/server/lights/LightsService.javasetFlashing方法里面setLightLocked来实现等效。

所有对灯效的操作都是通过setLightLocked实现。如下

        private void setLightLocked(int color, int mode, int onMS, int offMS, int brightnessMode) {

            if (color != mColor || mode != mMode || onMS != mOnMS || offMS != mOffMS) {

                if (DEBUG) Slog.v(TAG, "setLight #" + mId + ": color=#"

                        + Integer.toHexString(color));

                mColor = color;

                mMode = mode;

                mOnMS = onMS;

                mOffMS = offMS;

                Trace.traceBegin(Trace.TRACE_TAG_POWER, "setLight(" + mId + ", " + color + ")");

                try {

                    setLight_native(mNativePointer, mId, color, mode, onMS, offMS, brightnessMode);

                } finally {

                    Trace.traceEnd(Trace.TRACE_TAG_POWER);

                }

            }

        }

 

        private int mId;

        private int mColor;

        private int mMode;

        private int mOnMS;

        private int mOffMS;

        private boolean mFlashing;

    }

setLight_native最终调用了一个native方法,到JNI层去了。

 

frameworks/base/services/core/jni/com_android_server_lights_LightsService.cpp中还是将LED灯颜色,模式,时间写入state中向下继续传递

static void setLight_native(JNIEnv *env, jobject clazz, jlong ptr,

        jint light, jint colorARGB, jint flashMode, jint onMS, jint offMS, jint brightnessMode)

{

    Devices* devices = (Devices*)ptr;

    light_state_t state;

    if (light < 0 || light >= LIGHT_COUNT || devices->lights[light] == NULL) {

        return ;

    }

    memset(&state, 0, sizeof(light_state_t));

    state.color = colorARGB;

    state.flashMode = flashMode;

    state.flashOnMS = onMS;

    state.flashOffMS = offMS;

    state.brightnessMode = brightnessMode;

    {

        ALOGD_IF_SLOW(50, "Excessive delay setting light");

        devices->lights[light]->set_light(devices->lights[light], &state);

    }

}

最后通过hardwareinterface控制led灯颜色节点实现灯效的具体效果!

猜你喜欢

转载自blog.csdn.net/chi_wy/article/details/43404731