勤能补拙,熟能生巧,宁静致远

记录工作中的点滴积累,总结成长的步伐里程。

博客园 首页 新随笔 联系 订阅 管理

灭屏状态下,接收新信息,屏幕会半亮显示通知流程

1,应用构造notification后,传给NotificationManager,而后进入NotificationManagerService处理。 

NotificationManager nm = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);

nm.notify(NOTIFICATION_ID, notification)

 frameworks\base\core\java\android\app\NotificationManager.java

public void notify(int id, Notification notification)
    {
        notify(null, id, notification);
    }
public void notify(String tag, int id, Notification 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) {
        }
}

frameworks\base\services\core\java\com\android\server\notification\NotificationManagerService.java

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);
        }

同一个包名的通知超过50条不会继续处理。


if (count >= MAX_PACKAGE_NOTIFICATIONS) {
Slog.e(TAG, "Package has already posted " + count
+ " notifications. Not showing more. package=" + pkg);
return;
}

private void buzzBeepBlinkLocked(NotificationRecord record) {
……
……
// light
        // release the light
        boolean wasShowLights = mLights.remove(record.getKey());
        if ((notification.flags & Notification.FLAG_SHOW_LIGHTS) != 0 && aboveThreshold) {
            mLights.add(record.getKey());
            updateLightsLocked();
            if (mUseAttentionLight) {
                mAttentionLight.pulse();
            }
            blink = true;
        } else if (wasShowLights) {
            updateLightsLocked();
        }
        if (buzz || beep || blink) {
            EventLogTags.writeNotificationAlert(record.getKey(),
                    buzz ? 1 : 0, beep ? 1 : 0, blink ? 1 : 0);
            mHandler.post(mBuzzBeepBlinked);
        }

}

屏幕半亮闪烁需要判断 (notification.flags & Notification.FLAG_SHOW_LIGHTS) != 0

所以在应用构建notification时可以通过给flag赋值来控制是否要屏幕半亮闪烁。 

先读取设置数据库中的NOTIFICATION_LIGHT_PULSE来判断是否闪烁,如果mNotificationPulseEnabled为true,则先闪烁一次(Light.LIGHT_FLASH_TIMED =1)。

Settings.System.getInt(resolver, Settings.System.NOTIFICATION_LIGHT_PULSE, 0)
if (mNotificationPulseEnabled) {
// pulse repeatedly
mNotificationLight.setFlashing(ledARGB, Light.LIGHT_FLASH_TIMED,  //Light.LIGHT_FLASH_TIMED =1
ledOnMS, ledOffMS);
}
// let SystemUI make an independent decision //进入SystemUI处理
mStatusBar.notificationLightPulse(ledARGB, ledOnMS, ledOffMS);


2,然后进入SystemUi继续处理。
SystemUI中最终处理在DozeService中,也有一个开关判断,是否要闪烁。
if (!mDozeParameters.getPulseOnNotifications()) return;//getPulseOnNotifications默认为true

DozeService.java中调用private void requestPulse(final int reason)执行点亮屏幕。

private void requestPulse(final int reason, boolean performedProxCheck) {
        if (mHost != null && mDreaming && !mPulsing) {
            // Let the host know we want to pulse.  Wait for it to be ready, then
            // turn the screen on.  When finished, turn the screen off again.
            // Here we need a wakelock to stay awake until the pulse is finished.
            mWakeLock.acquire();
            mPulsing = true;
            if (!mDozeParameters.getProxCheckBeforePulse()) {//这里先判断是否要先执行ProxCheck, proxCheck会检查手机sensor是否正常,如果不正常就退出,不执行点亮屏幕
                // skip proximity check
                continuePulsing(reason);
                return;
            }
            final long start = SystemClock.uptimeMillis();
            if (performedProxCheck) {
                // the caller already performed a successful proximity check; we'll only do one to
                // capture statistics, continue pulsing immediately.
                continuePulsing(reason);
            }
            // perform a proximity check
            new ProximityCheck() {
                @Override
                public void onProximityResult(int result) {
                    ……
                                  ……
                }
            }.check();
        }
    }
    
    private abstract class ProximityCheck implements SensorEventListener, Runnable {
            ……
            ……
            public void check() {
            if (mFinished || mRegistered) return;
            final Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
            if (sensor == null) {//手机sensor无效,直接退出程序。
                if (DEBUG) Log.d(mTag, "No sensor found");
                finishWithResult(RESULT_UNKNOWN);
                return;
            }
            // the pickup sensor interferes with the prox event, disable it until we have a result
            mPickupSensor.setDisabled(true);

            mMaxRange = sensor.getMaximumRange();
            mSensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_NORMAL, 0,
                    mHandler);
            mHandler.postDelayed(this, TIMEOUT_DELAY_MS);
            mRegistered = true;
        }
            
            ……
            ……
    }

 

----------------------------------------------------------------------------------------------------

 

3,SystemUI下拉展开布局中显示通知处理流程

BaseStatusBar中通过mNotificationListener监听通知更新,获取通知

 private final NotificationListenerService mNotificationListener =
            new NotificationListenerService() {
            
             public void onListenerConnected() {
                if (DEBUG) Log.d(TAG, "onListenerConnected");
                final StatusBarNotification[] notifications = getActiveNotifications();//获取当前所有通知集合
                final RankingMap currentRanking = getCurrentRanking();
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        for (StatusBarNotification sbn : notifications) {
                            addNotification(sbn, currentRanking, null /* oldEntry */);
                        }
                    }
                });
                }
            ……
    }

NotificationListenerService获取通知
   public StatusBarNotification[] getActiveNotifications() {
        return getActiveNotifications(null, TRIM_FULL);
    }
    
    public StatusBarNotification[] getActiveNotifications(String[] keys, int trim) {
        if (!isBound())
            return null;
        try {
            //这里通过Binder调用NotificationManagerService调用getActiveNotificationsFromListener获取通知
            ParceledListSlice<StatusBarNotification> parceledList = getNotificationInterface().getActiveNotificationsFromListener(mWrapper, keys, trim);
            List<StatusBarNotification> list = parceledList.getList();
            …………
            return list.toArray(new StatusBarNotification[list.size()]);
        } catch (android.os.RemoteException ex) {
            Log.v(TAG, "Unable to contact notification manager", ex);
        }
        return null;
    }
    
    //获取INotificationManager的实例,也就是NotificationManagerService中的mService
    private final INotificationManager getNotificationInterface() {
        if (mNoMan == null) {
            mNoMan = INotificationManager.Stub.asInterface(
                    ServiceManager.getService(Context.NOTIFICATION_SERVICE));
        }
        return mNoMan;
    }
NotificationManagerService中对Context.NOTIFICATION_SERVICE的映射
public class NotificationManagerService extends SystemService
    public void onStart() {
            ……
            publishBinderService(Context.NOTIFICATION_SERVICE, mService);//SystemService中定义的方法 publishBinderService(..)
        ……
    }

通过上述流程已经获取通知数据,将数据显示在SystemUI中在PhoneStatusBar中处理

  //重载父类BaseStatusBar中的方法,mNotificationListener中会直接调用这里添加通知
    public void addNotification(StatusBarNotification notification, RankingMap ranking, Entry oldEntry) {
        if (DEBUG) Log.d(TAG, "addNotification key=" + notification.getKey());

        Entry shadeEntry = createNotificationViews(notification);
        if (shadeEntry == null) {
            return;
        }
        ……
        addNotificationViews(shadeEntry, ranking);//
        // Recalculate the position of the sliding windows and the titles.
        setAreThereNotifications();
    }
  protected void addNotificationViews(Entry entry, RankingMap ranking) {
        if (entry == null) {
            return;
        }
        // Add the expanded view and icon.
        mNotificationData.add(entry, ranking);//
        updateNotifications(); //此方法会将新通知添加到SystemUI布局中显示
    }

 

posted on 2016-06-01 15:08  ^-^antoon^-^  阅读(6985)  评论(0编辑  收藏  举报