平台

RK3288 + Android 5.1

SystemUI 启动:

|-- frameworks/base/services/java/com/android/server/SystemServer.java

    private void startOtherServices() {...        mActivityManagerService.systemReady(new Runnable() {            @Override            public void run() {                Slog.i(TAG, "Making services ready");....                try {                    startSystemUi(context);                } catch (Throwable e) {                    reportWtf("starting System UI", e);                }...}}    static final void startSystemUi(Context context) {        Intent intent = new Intent();        intent.setComponent(new ComponentName("com.android.systemui",                    "com.android.systemui.SystemUIService"));        //Slog.d(TAG, "Starting service: " + intent);        context.startServiceAsUser(intent, UserHandle.OWNER);    }

启动的时间, 是在系统服务ready时候, 这时个WindowManagerService, ActivityManagerService, PackageManagerService等关键的服务已经就绪.

|-- frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIService.java

public class SystemUIService extends Service {    @Override    public void onCreate() {        super.onCreate();//关键代码:        ((SystemUIApplication) getApplication()).startServicesIfNeeded();    }    @Override    public IBinder onBind(Intent intent) {        return null;    }    @Override    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {        SystemUI[] services = ((SystemUIApplication) getApplication()).getServices();        if (args == null || args.length == 0) {            for (SystemUI ui: services) {                pw.println("dumping service: " + ui.getClass().getName());                ui.dump(fd, pw, args);            }        } else {            String svc = args[0];            for (SystemUI ui: services) {                String name = ui.getClass().getName();                if (name.endsWith(svc)) {                    ui.dump(fd, pw, args);                }            }        }    }}

|-- frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java

    /**     * The classes of the stuff to start.     */    private final Class<?>[] SERVICES = new Class[] {            com.android.systemui.keyguard.KeyguardViewMediator.class,            com.android.systemui.recent.Recents.class,            com.android.systemui.volume.VolumeUI.class,            com.android.systemui.statusbar.SystemBars.class,            com.android.systemui.usb.StorageNotification.class,            com.android.systemui.power.PowerUI.class,            com.android.systemui.media.RingtonePlayer.class    };    public void startServicesIfNeeded() {        if (mServicesStarted) {            return;        }        if (!mBootCompleted) {            // check to see if maybe it was already completed long before we began            // see ActivityManagerService.finishBooting()            if ("1".equals(SystemProperties.get("sys.boot_completed"))) {                mBootCompleted = true;                if (DEBUG) Log.v(TAG, "BOOT_COMPLETED was already sent");            }        }/**----启动 SERVICES 所有的组件:----**/        Log.v(TAG, "Starting SystemUI services.");        final int N = SERVICES.length;        for (int i=0; i<N; i++) {            Class<?> cl = SERVICES[i];            if (DEBUG) Log.d(TAG, "loading: " + cl);            try {                mServices[i] = (SystemUI)cl.newInstance();            } catch (IllegalAccessException ex) {                throw new RuntimeException(ex);            } catch (InstantiationException ex) {                throw new RuntimeException(ex);            }            mServices[i].mContext = this;            mServices[i].mComponents = mComponents;            if (DEBUG) Log.d(TAG, "running: " + mServices[i]);            mServices[i].start();            if (mBootCompleted) {                mServices[i].onBootCompleted();            }        }        mServicesStarted = true;    }

重点关注 com.android.systemui.statusbar.SystemBars.class, 聚焦后面我们研究状态栏.

状态栏 + 导航栏的核心 PhoneStatusBar

|-- frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/SystemBars.java

    @Override    public void start() {        if (DEBUG) Log.d(TAG, "start");        mServiceMonitor = new ServiceMonitor(TAG, DEBUG,                mContext, Settings.Secure.BAR_SERVICE_COMPONENT, this);        mServiceMonitor.start();  // will call onNoService if no remote service is found    }

因为在公版代码中, 并未设置 BAR_SERVICE_COMPONENT 所以, ServiceMonitor执行start后, 会回调

    @Override    public void onNoService() {        if (DEBUG) Log.d(TAG, "onNoService");        createStatusBarFromConfig();  // fallback to using an in-process implementation    }private void createStatusBarFromConfig() {        if (DEBUG) Log.d(TAG, "createStatusBarFromConfig");        String clsName = mContext.getString(R.string.config_statusBarComponent);/** frameworks/base/packages/SystemUI/res/values/config.xml:    com.android.systemui.statusbar.phone.PhoneStatusBar**/        if ("box".equals(SystemProperties.get("ro.target.product", "tablet"))&&!mContext.getResources().getConfiguration().enableMultiWindow()){            clsName = "com.android.systemui.statusbar.tv.TvStatusBar";        }        if (clsName == null || clsName.length() == 0) {            throw andLog("No status bar component configured", null);        }        Class<?> cls = null;        try {            cls = mContext.getClassLoader().loadClass(clsName);        } catch (Throwable t) {            throw andLog("Error loading status bar component: " + clsName, t);        }        try {            mStatusBar = (BaseStatusBar) cls.newInstance();        } catch (Throwable t) {            throw andLog("Error creating status bar component: " + clsName, t);        }        mStatusBar.mContext = mContext;        mStatusBar.mComponents = mComponents;        mStatusBar.start();        if (DEBUG) Log.d(TAG, "started " + mStatusBar.getClass().getSimpleName());    }

到此, 终于进入主角: PhoneStatusBar

|-- frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java

    public void start() {//父类BaseStatusBar的函数        ...        mBarService = IStatusBarService.Stub.asInterface(                ServiceManager.getService(Context.STATUS_BAR_SERVICE));        mRecents = getComponent(RecentsComponent.class);        mRecents.setCallback(this);        final Configuration currentConfig = mContext.getResources().getConfiguration();        mLocale = currentConfig.locale;        mLayoutDirection = TextUtils.getLayoutDirectionFromLocale(mLocale);        mFontScale = currentConfig.fontScale;        mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);        mLinearOutSlowIn = AnimationUtils.loadInterpolator(mContext,                android.R.interpolator.linear_out_slow_in);        mFastOutLinearIn = AnimationUtils.loadInterpolator(mContext,                android.R.interpolator.fast_out_linear_in);        // Connect in to the status bar manager service        StatusBarIconList iconList = new StatusBarIconList();        mCommandQueue = new CommandQueue(this, iconList);        .../** ----添加状态栏----**/        createAndAddWindows();        ...    }
    @Override    public void start() {        mDisplay = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))                .getDefaultDisplay();        updateDisplaySize();        mScrimSrcModeEnabled = mContext.getResources().getBoolean(                R.bool.config_status_bar_scrim_behind_use_src);        super.start(); // calls createAndAddWindows()        ...        // TODO: use MediaSessionManager.SessionListener to hook us up to future updates        // in session state/** ----添加导航栏(BACK, HOME, RECENT)----**/        addNavigationBar();        ...    }// For small-screen devices (read: phones) that lack hardware navigation buttons    private void addNavigationBar() {        if (DEBUG) Log.v(TAG, "addNavigationBar: about to add " + mNavigationBarView);        if (mNavigationBarView == null) return;        prepareNavigationBarView();        mWindowManager.addView(mNavigationBarView, getNavigationBarLayoutParams());    }
    @Override    public void createAndAddWindows() {wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);        mWallpaperManager = (WallpaperManager) mContext.getSystemService(Context.WALLPAPER_SERVICE);        addMultiModeWindow();        addStatusBarWindow();addHalfScreenWindowController();if(IS_USE_WHCONTROLS){addFourScreenWindowController();}addCenterBtnWindow();if(ONE_LEVEL_MENU){addCircleMenuWindow();}if(IS_USE_BACK_WINDOW){if(mFourScreenBackWindow == null){mFourScreenBackWindow = new FourScreenBackWindow(mContext, wm);}}if(mMinWindow == null){mMinWindow = new MinWindow(mContext, wm);}    }    private void addStatusBarWindow() {        makeStatusBarView();        mStatusBarWindowManager = new StatusBarWindowManager(mContext);        mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight());    }    // ================================================================================    // Constructing the view    // ================================================================================    protected PhoneStatusBarView makeStatusBarView() {        final Context context = mContext;        IntentFilter intentfilter=new IntentFilter();        intentfilter.addAction("rk.android.screenshot.SHOW");        intentfilter.addAction("rk.android.screenshot.ACTION");        context.registerReceiver(receiver, intentfilter);IntentFilter winintentfilter=new IntentFilter();winintentfilter.addAction("rk.android.wintask.SHOW");winintentfilter.addAction("rk.android.wintask.FINISH");        context.registerReceiver(winreceiver, winintentfilter);        IntentFilter packagefilter=new IntentFilter();packagefilter.addAction(Intent.ACTION_PACKAGE_ADDED);    packagefilter.addAction(Intent.ACTION_PACKAGE_REMOVED);    packagefilter.addDataScheme("package");        context.registerReceiver(packagereceiver, packagefilter);            mContext.registerReceiver(wallpaperReceiver, new IntentFilter(Intent.ACTION_WALLPAPER_CHANGED));        Resources res = context.getResources();        updateDisplaySize(); // populates mDisplayMetrics        updateResources();        mIconSize = res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_icon_size);       if(mContext.getResources().getConfiguration().enableMultiWindow()){        mStatusBarWindow = (StatusBarWindowView) View.inflate(context,                R.layout.super_status_bar_win, null);       }else{        mStatusBarWindow = (StatusBarWindowView) View.inflate(context,                R.layout.super_status_bar, null);       }        mStatusBarWindow.mService = this;        mStatusBarWindow.setOnTouchListener(new View.OnTouchListener() {            @Override            public boolean onTouch(View v, MotionEvent event) {                checkUserAutohide(v, event);                if (event.getAction() == MotionEvent.ACTION_DOWN) {                    if (mExpandedVisible) {                        animateCollapsePanels();                    }                }                return mStatusBarWindow.onTouchEvent(event);            }});        mStatusBarView = (PhoneStatusBarView) mStatusBarWindow.findViewById(R.id.status_bar);        mStatusBarView.setBar(this);        PanelHolder holder = (PanelHolder) mStatusBarWindow.findViewById(R.id.panel_holder);        mStatusBarView.setPanelHolder(holder);mAppBarPanel = (AppBarPanelView)mStatusBarWindow.findViewById(R.id.appbar_panel);mAppBarPanel.setStatusBar(this);        mNotificationPanel = (NotificationPanelView) mStatusBarWindow.findViewById(R.id.notification_panel);        mNotificationPanel.setStatusBar(this);        if (!ActivityManager.isHighEndGfx()) {            mStatusBarWindow.setBackground(null);            mNotificationPanel.setBackground(new FastColorDrawable(context.getResources().getColor(                    R.color.notification_panel_solid_background)));mAppBarPanel.setBackground(new FastColorDrawable(context.getResources().getColor(                    R.color.notification_panel_solid_background)));        }        if (ENABLE_HEADS_UP) {           if(mContext.getResources().getConfiguration().enableMultiWindow()){            mHeadsUpNotificationView =                    (HeadsUpNotificationView) View.inflate(context, R.layout.heads_up_win, null);           } else {            mHeadsUpNotificationView =                    (HeadsUpNotificationView) View.inflate(context, R.layout.heads_up, null);           }            mHeadsUpNotificationView.setVisibility(View.GONE);            mHeadsUpNotificationView.setBar(this);        }        if (MULTIUSER_DEBUG) {            mNotificationPanelDebugText = (TextView) mNotificationPanel.findViewById(                    R.id.header_debug_info);            mNotificationPanelDebugText.setVisibility(View.VISIBLE);        }        updateShowSearchHoldoff();        try {            boolean showNav = mWindowManagerService.hasNavigationBar();            if (DEBUG) Log.v(TAG, "hasNavigationBar=" + showNav);            if (showNav) {            //haungjc:win bar                if(mContext.getResources().getConfiguration().enableMultiWindow()){            mNavigationBarView =                    (NavigationBarView) View.inflate(mContext, R.layout.navigation_bar_win, null);              }else{                mNavigationBarView =                    (NavigationBarView) View.inflate(mContext, R.layout.navigation_bar, null);              }                mNavigationBarView.setDisabledFlags(mDisabled);                mNavigationBarView.setBar(this);                mNavigationBarView.setOnVerticalChangedListener(                        new NavigationBarView.OnVerticalChangedListener() {                    @Override                    public void onVerticalChanged(boolean isVertical) {                        if (mSearchPanelView != null) {                            mSearchPanelView.setHorizontal(isVertical);                        }                        mNotificationPanel.setQsScrimEnabled(!isVertical);                    }                });                mNavigationBarView.setOnTouchListener(new View.OnTouchListener() {                    @Override                    public boolean onTouch(View v, MotionEvent event) {                        checkUserAutohide(v, event);                        return false;                    }});                      if(mContext.getResources().getConfiguration().enableMultiWindow()){               mNotificationLite = null;//new NotificationCenterLite(mContext);               mCalendarDialog   = new CalendarDialog(mContext);     }            }        } catch (RemoteException ex) {            // no window manager? good luck with that        }        // figure out which pixel-format to use for the status bar.        mPixelFormat = PixelFormat.OPAQUE;        mSystemIconArea = (LinearLayout) mStatusBarView.findViewById(R.id.system_icon_area);        mSystemIcons = (LinearLayout) mStatusBarView.findViewById(R.id.system_icons);        mStatusIcons = (LinearLayout)mStatusBarView.findViewById(R.id.statusIcons);        mNotificationIconArea = mStatusBarView.findViewById(R.id.notification_icon_area_inner);        mNotificationIcons = (IconMerger)mStatusBarView.findViewById(R.id.notificationIcons);        mMoreIcon = mStatusBarView.findViewById(R.id.moreIcon);        mNotificationIcons.setOverflowIndicator(mMoreIcon);        mStatusBarContents = (LinearLayout)mStatusBarView.findViewById(R.id.status_bar_contents);        mSimSwitchNotification = (LinearLayout) mStatusBarView.findViewById(                R.id.simSwitchNotification);        mSimSwitchNotificationText = (TextView) mStatusBarView.findViewById(                R.id.simSwitchNotificationText);        mSimSwitchContainer = (LinearLayout) mStatusBarWindow.findViewById(                R.id.sim_switch_container);        mSim1Container = (LinearLayout)mStatusBarWindow.findViewById(R.id.sim1_container);        mSim2Container = (LinearLayout)mStatusBarWindow.findViewById(R.id.sim2_container);        mAskContainer = (LinearLayout)mStatusBarWindow.findViewById(R.id.ask_container);        mSwitchSim1Button = (ImageView)mStatusBarWindow.findViewById(R.id.sim1_switch_button);        mSwitchSim2Button = (ImageView)mStatusBarWindow.findViewById(R.id.sim2_switch_button);        mSwitchAskButton = (ImageView)mStatusBarWindow.findViewById(R.id.ask_switch_button);        mSwitchSim1Button.setOnClickListener(mSimSwitchListener);        mSwitchSim2Button.setOnClickListener(mSimSwitchListener);        mSwitchAskButton.setOnClickListener(mSimSwitchListener);        mStackScroller = (NotificationStackScrollLayout) mStatusBarWindow.findViewById(                R.id.notification_stack_scroller);        mStackScroller.setLongPressListener(getNotificationLongClicker());        mStackScroller.setPhoneStatusBar(this);        mKeyguardIconOverflowContainer =                (NotificationOverflowContainer) LayoutInflater.from(mContext).inflate(                        R.layout.status_bar_notification_keyguard_overflow, mStackScroller, false);        mKeyguardIconOverflowContainer.setOnActivatedListener(this);        mKeyguardIconOverflowContainer.setOnClickListener(mOverflowClickListener);        mStackScroller.addView(mKeyguardIconOverflowContainer);        SpeedBumpView speedBump = (SpeedBumpView) LayoutInflater.from(mContext).inflate(                        R.layout.status_bar_notification_speed_bump, mStackScroller, false);        mStackScroller.setSpeedBumpView(speedBump);        mEmptyShadeView = (EmptyShadeView) LayoutInflater.from(mContext).inflate(                R.layout.status_bar_no_notifications, mStackScroller, false);        mStackScroller.setEmptyShadeView(mEmptyShadeView);        mDismissView = (DismissView) LayoutInflater.from(mContext).inflate(                R.layout.status_bar_notification_dismiss_all, mStackScroller, false);        mDismissView.setOnButtonClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                clearAllNotifications();            }        });        mStackScroller.setDismissView(mDismissView);        mExpandedContents = mStackScroller;        mBackdrop = (BackDropView) mStatusBarWindow.findViewById(R.id.backdrop);        mBackdropFront = (ImageView) mBackdrop.findViewById(R.id.backdrop_front);        mBackdropBack = (ImageView) mBackdrop.findViewById(R.id.backdrop_back);        ScrimView scrimBehind = (ScrimView) mStatusBarWindow.findViewById(R.id.scrim_behind);        ScrimView scrimInFront = (ScrimView) mStatusBarWindow.findViewById(R.id.scrim_in_front);        mScrimController = new ScrimController(scrimBehind, scrimInFront, mScrimSrcModeEnabled);        mScrimController.setBackDropView(mBackdrop);        mStatusBarView.setScrimController(mScrimController);        mDozeScrimController = new DozeScrimController(mScrimController, context);        mHeader = (StatusBarHeaderView) mStatusBarWindow.findViewById(R.id.header);        mHeader.setActivityStarter(this);        mKeyguardStatusBar = (KeyguardStatusBarView) mStatusBarWindow.findViewById(R.id.keyguard_header);        mStatusIconsKeyguard = (LinearLayout) mKeyguardStatusBar.findViewById(R.id.statusIcons);        mKeyguardStatusView = mStatusBarWindow.findViewById(R.id.keyguard_status_view);        mKeyguardBottomArea =                (KeyguardBottomAreaView) mStatusBarWindow.findViewById(R.id.keyguard_bottom_area);        mKeyguardBottomArea.setActivityStarter(this);        mKeyguardIndicationController = new KeyguardIndicationController(mContext,                (KeyguardIndicationTextView) mStatusBarWindow.findViewById(                        R.id.keyguard_indication_text));        mKeyguardBottomArea.setKeyguardIndicationController(mKeyguardIndicationController);        mTickerEnabled = res.getBoolean(R.bool.enable_ticker);        if (mTickerEnabled) {            final ViewStub tickerStub = (ViewStub) mStatusBarView.findViewById(R.id.ticker_stub);            if (tickerStub != null) {                mTickerView = tickerStub.inflate();                mTicker = new MyTicker(context, mStatusBarView);                TickerView tickerView = (TickerView) mStatusBarView.findViewById(R.id.tickerText);                tickerView.mTicker = mTicker;            }        }        mEdgeBorder = res.getDimensionPixelSize(R.dimen.status_bar_edge_ignore);        // set the inital view visibility        setAreThereNotifications();        // Background thread for any controllers that need it.        mHandlerThread = new HandlerThread(TAG, Process.THREAD_PRIORITY_BACKGROUND);        mHandlerThread.start();        // Other icons        mLocationController = new LocationControllerImpl(mContext); // will post a notification        mBatteryController = new BatteryController(mContext);mBatteryController.setPercentageView((TextView) mStatusBarWindow.findViewById(R.id.battery_percentage));        mBatteryController.addStateChangedCallback(new BatteryStateChangeCallback() {            @Override            public void onPowerSaveChanged() {                mHandler.post(mCheckBarModes);                if (mDozeServiceHost != null) {                    mDozeServiceHost.firePowerSaveChanged(mBatteryController.isPowerSave());                }            }            @Override            public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {                // noop            }        });        mNetworkController = new NetworkControllerImpl(mContext);        mHotspotController = new HotspotControllerImpl(mContext);        mBluetoothController = new BluetoothControllerImpl(mContext, mHandlerThread.getLooper());        mSecurityController = new SecurityControllerImpl(mContext);        if (mContext.getResources().getBoolean(R.bool.config_showRotationLock)) {            mRotationLockController = new RotationLockControllerImpl(mContext);        }        mUserInfoController = new UserInfoController(mContext);        mVolumeComponent = getComponent(VolumeComponent.class);        if (mVolumeComponent != null) {            mZenModeController = mVolumeComponent.getZenController();        }        mCastController = new CastControllerImpl(mContext);        final SignalClusterView signalCluster =                (SignalClusterView) mStatusBarView.findViewById(R.id.signal_cluster);        final SignalClusterView signalClusterKeyguard =                (SignalClusterView) mKeyguardStatusBar.findViewById(R.id.signal_cluster);        final SignalClusterView signalClusterQs =                (SignalClusterView) mHeader.findViewById(R.id.signal_cluster);        mNetworkController.addSignalCluster(signalCluster);        mNetworkController.addSignalCluster(signalClusterKeyguard);        mNetworkController.addSignalCluster(signalClusterQs);        signalCluster.setSecurityController(mSecurityController);        signalCluster.setNetworkController(mNetworkController);        signalClusterKeyguard.setSecurityController(mSecurityController);        signalClusterKeyguard.setNetworkController(mNetworkController);        signalClusterQs.setSecurityController(mSecurityController);        signalClusterQs.setNetworkController(mNetworkController);if(mContext.getResources().getConfiguration().enableMultiWindow()){   if(signalCluster_win==null&&mNavigationBarView!=null){   mStatusIcons_win = mNavigationBarView.getStatusIcons_win();    signalCluster_win = (SignalClusterView) mNavigationBarView.findViewById(R.id.signal_cluster);mNetworkController.addSignalCluster(signalCluster_win);signalCluster_win.setSecurityController(mSecurityController);            signalCluster_win.setNetworkController(mNetworkController);}}        final boolean isAPhone = mNetworkController.hasVoiceCallingFeature();        if (isAPhone) {            mNetworkController.addEmergencyListener(new NetworkControllerImpl.EmergencyListener() {                @Override                public void setEmergencyCallsOnly(boolean emergencyOnly) {                    mHeader.setShowEmergencyCallsOnly(emergencyOnly);                }            });        }        mCarrierLabel = (TextView)mStatusBarWindow.findViewById(R.id.carrier_label);        mShowCarrierInPanel = (mCarrierLabel != null);        if (DEBUG) Log.v(TAG, "carrierlabel=" + mCarrierLabel + " show=" + mShowCarrierInPanel);        if (mShowCarrierInPanel) {            mCarrierLabel.setVisibility(mCarrierLabelVisible ? View.VISIBLE : View.INVISIBLE);            mNetworkController.addCarrierLabel(new NetworkControllerImpl.CarrierLabelListener() {                @Override                public void setCarrierLabel(String label) {                    mCarrierLabel.setText(label);                    if (mNetworkController.hasMobileDataFeature()) {                        if (TextUtils.isEmpty(label)) {                            mCarrierLabel.setVisibility(View.GONE);                        } else {                            mCarrierLabel.setVisibility(View.VISIBLE);                        }                    }                }            });        }        mFlashlightController = new FlashlightController(mContext);        mKeyguardBottomArea.setFlashlightController(mFlashlightController);        mKeyguardBottomArea.setPhoneStatusBar(this);        mAccessibilityController = new AccessibilityController(mContext);        mKeyguardBottomArea.setAccessibilityController(mAccessibilityController);        mNextAlarmController = new NextAlarmController(mContext);        mKeyguardMonitor = new KeyguardMonitor();        if (UserSwitcherController.isUserSwitcherAvailable(UserManager.get(mContext))) {            mUserSwitcherController = new UserSwitcherController(mContext, mKeyguardMonitor);        }        mKeyguardUserSwitcher = new KeyguardUserSwitcher(mContext,                (ViewStub) mStatusBarWindow.findViewById(R.id.keyguard_user_switcher),                mKeyguardStatusBar, mNotificationPanel, mUserSwitcherController);        // Set up the quick settings tile panel        mQSPanel = (QSPanel) mStatusBarWindow.findViewById(R.id.quick_settings_panel);        if (mQSPanel != null) {            final QSTileHost qsh = new QSTileHost(mContext, this,                    mBluetoothController, mLocationController, mRotationLockController,                    mNetworkController, mZenModeController, mHotspotController,                    mCastController, mFlashlightController,                    mUserSwitcherController, mKeyguardMonitor,                    mSecurityController);            mQSPanel.setHost(qsh);            mQSPanel.setTiles(qsh.getTiles());            mBrightnessMirrorController = new BrightnessMirrorController(mStatusBarWindow);            mQSPanel.setBrightnessMirror(mBrightnessMirrorController);            mHeader.setQSPanel(mQSPanel);            qsh.setCallback(new QSTileHost.Callback() {                @Override                public void onTilesChanged() {                    mQSPanel.setTiles(qsh.getTiles());                }            });        }        // User info. Trigger first load.        mHeader.setUserInfoController(mUserInfoController);        mKeyguardStatusBar.setUserInfoController(mUserInfoController);        mUserInfoController.reloadUserInfo();        mHeader.setBatteryController(mBatteryController);        ((BatteryMeterView) mStatusBarView.findViewById(R.id.battery)).setBatteryController(                mBatteryController);//AnsonCode hide batteryif(!mContext.getResources().getBoolean(R.bool.config_has_battery)){mStatusBarView.findViewById(R.id.battery).setVisibility(View.GONE);}        mKeyguardStatusBar.setBatteryController(mBatteryController);        mHeader.setNextAlarmController(mNextAlarmController);        PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);        mBroadcastReceiver.onReceive(mContext,                new Intent(pm.isScreenOn() ? Intent.ACTION_SCREEN_ON : Intent.ACTION_SCREEN_OFF));        // receive broadcasts        IntentFilter filter = new IntentFilter();        filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);        filter.addAction(Intent.ACTION_SCREEN_OFF);        filter.addAction(Intent.ACTION_SCREEN_ON);        if (DEBUG_MEDIA_FAKE_ARTWORK) {            filter.addAction("fake_artwork");        }        filter.addAction(ACTION_DEMO);        context.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null);        // listen for USER_SETUP_COMPLETE setting (per-user)        resetUserSetupObserver();        startGlyphRasterizeHack();        return mStatusBarView;    }

|-- frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java

    /**     * Adds the status bar view to the window manager.     *     * @param statusBarView The view to add.     * @param barHeight The height of the status bar in collapsed state.     */    public void add(View statusBarView, int barHeight) {        // Now that the status bar window encompasses the sliding panel and its        // translucent backdrop, the entire thing is made TRANSLUCENT and is        // hardware-accelerated.        mLp = new WindowManager.LayoutParams(                ViewGroup.LayoutParams.MATCH_PARENT,                barHeight,                WindowManager.LayoutParams.TYPE_STATUS_BAR,                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE                        | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING                        | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH                        | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH                        | WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,                PixelFormat.TRANSLUCENT);        mLp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;        mLp.gravity = Gravity.TOP;        mLp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;        mLp.setTitle("StatusBar");        mLp.packageName = mContext.getPackageName();        mStatusBarView = statusBarView;        mBarHeight = barHeight;/**----注释即可不显示 ----**/        mWindowManager.addView(mStatusBarView, mLp);        mLpChanged = new WindowManager.LayoutParams();        mLpChanged.copyFrom(mLp);    }

状态栏 和导航栏, 通过WindowManager.addView添加并显示.

[扩展]

去除状态栏的方式有
1. 把状态栏高度设置为0;
2. 删除 mWindowManager.addView(mStatusBarView, mLp);

去除HEADS-UP通知显示

在5.0后, android 增加了新的通知提示方式(HEADS-UP), 让用户能在任何界面(即使全屏)不会错过重要通知.

        Notification.Builder builder = new Notification.Builder(this);        builder.setContentTitle("通知");        builder.setContentText("横幅提醒");        builder.setDefaults(Notification.DEFAULT_ALL);        builder.setSmallIcon(R.mipmap.ic_launcher);        builder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher));        Intent intent = new Intent(this, EntranceActivity.class);        PendingIntent pIntent = PendingIntent.getActivity(this, 1, intent, 0);        builder.setContentIntent(pIntent);/**----重点----***/        builder.setFullScreenIntent(pIntent, true);        builder.setAutoCancel(true);

setFullScreenIntent 干了什么:

|-- frameworks/base/core/java/android/app/Notification.java

        public Builder setFullScreenIntent(PendingIntent intent, boolean highPriority) {/**---- mFullScreenIntent赋了非空 ----**/mFullScreenIntent = intent;            setFlag(FLAG_HIGH_PRIORITY, highPriority);            return this;        }

发送通知:

|-- frameworks/base/services/core/java/com/android/server/notification/NotificationManagerService.java

        @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 Notification notification,            int[] idOut, int incomingUserId) {        if (DBG) {            Slog.v(TAG, "enqueueNotificationInternal: pkg=" + pkg + " id=" + id                    + " notification=" + notification);        }        checkCallerIsSystemOrSameApp(pkg);        final boolean isSystemNotification = isUidSystem(callingUid) || ("android".equals(pkg));        final boolean isNotificationFromListener = mListeners.isListenerPackage(pkg);        final int userId = ActivityManager.handleIncomingUser(callingPid,                callingUid, incomingUserId, true, false, "enqueueNotification", pkg);        final UserHandle user = new UserHandle(userId);        // Limit the number of notifications that any given package except the android        // package or a registered listener can enqueue.  Prevents DOS attacks and deals with leaks.        if (!isSystemNotification && !isNotificationFromListener) {            synchronized (mNotificationList) {                int count = 0;                final int N = mNotificationList.size();                for (int i=0; i<N; i++) {                    final NotificationRecord r = mNotificationList.get(i);                    if (r.sbn.getPackageName().equals(pkg) && r.sbn.getUserId() == userId) {                        count++;                        if (count >= MAX_PACKAGE_NOTIFICATIONS) {                            Slog.e(TAG, "Package has already posted " + count                                    + " notifications.  Not showing more.  package=" + pkg);                            return;                        }                    }                }            }        }        if (pkg == null || notification == null) {            throw new IllegalArgumentException("null not allowed: pkg=" + pkg                    + " id=" + id + " notification=" + notification);        }        if (notification.icon != 0) {            if (!notification.isValid()) {                throw new IllegalArgumentException("Invalid notification (): pkg=" + pkg                        + " id=" + id + " notification=" + notification);            }        }        mHandler.post(new Runnable() {            @Override            public void run() {                synchronized (mNotificationList) {                    // === Scoring ===                    // 0. Sanitize inputs                    notification.priority = clamp(notification.priority, Notification.PRIORITY_MIN,                            Notification.PRIORITY_MAX);                    // Migrate notification flags to scores                    if (0 != (notification.flags & Notification.FLAG_HIGH_PRIORITY)) {                        if (notification.priority < Notification.PRIORITY_MAX) {                            notification.priority = Notification.PRIORITY_MAX;                        }                    } else if (SCORE_ONGOING_HIGHER &&                            0 != (notification.flags & Notification.FLAG_ONGOING_EVENT)) {                        if (notification.priority < Notification.PRIORITY_HIGH) {                            notification.priority = Notification.PRIORITY_HIGH;                        }                    }                    // 1. initial score: buckets of 10, around the app [-20..20]                    final int score = notification.priority * NOTIFICATION_PRIORITY_MULTIPLIER;                    // 2. extract ranking signals from the notification data                    final StatusBarNotification n = new StatusBarNotification(                            pkg, opPkg, id, tag, callingUid, callingPid, score, notification,                            user);                    NotificationRecord r = new NotificationRecord(n, score);                    NotificationRecord old = mNotificationsByKey.get(n.getKey());                    if (old != null) {                        // Retain ranking information from previous record                        r.copyRankingInformation(old);                    }                    // Handle grouped notifications and bail out early if we                    // can to avoid extracting signals.                    handleGroupedNotificationLocked(r, old, callingUid, callingPid);                    boolean ignoreNotification =                            removeUnusedGroupedNotificationLocked(r, old, callingUid, callingPid);                    // This conditional is a dirty hack to limit the logging done on                    //     behalf of the download manager without affecting other apps.                    if (!pkg.equals("com.android.providers.downloads")                            || Log.isLoggable("DownloadManager", Log.VERBOSE)) {                        int enqueueStatus = EVENTLOG_ENQUEUE_STATUS_NEW;                        if (ignoreNotification) {                            enqueueStatus = EVENTLOG_ENQUEUE_STATUS_IGNORED;                        } else if (old != null) {                            enqueueStatus = EVENTLOG_ENQUEUE_STATUS_UPDATE;                        }                        EventLogTags.writeNotificationEnqueue(callingUid, callingPid,                                pkg, id, tag, userId, notification.toString(),                                enqueueStatus);                    }                    if (ignoreNotification) {                        return;                    }                    mRankingHelper.extractSignals(r);                    // 3. Apply local rules                    // blocked apps                    if (ENABLE_BLOCKED_NOTIFICATIONS && !noteNotificationOp(pkg, callingUid)) {                        if (!isSystemNotification) {                            r.score = JUNK_SCORE;                            Slog.e(TAG, "Suppressing notification from package " + pkg                                    + " by user request.");                        }                    }                    if (r.score < SCORE_DISPLAY_THRESHOLD) {                        // Notification will be blocked because the score is too low.                        return;                    }                    int index = indexOfNotificationLocked(n.getKey());                    if (index < 0) {                        mNotificationList.add(r);                        mUsageStats.registerPostedByApp(r);                    } else {                        old = mNotificationList.get(index);                        mNotificationList.set(index, r);                        mUsageStats.registerUpdatedByApp(r, old);                        // Make sure we don't lose the foreground service state.                        notification.flags |=                                old.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE;                        r.isUpdate = true;                    }                    mNotificationsByKey.put(n.getKey(), r);                    // Ensure if this is a foreground service that the proper additional                    // flags are set.                    if ((notification.flags & Notification.FLAG_FOREGROUND_SERVICE) != 0) {                        notification.flags |= Notification.FLAG_ONGOING_EVENT                                | Notification.FLAG_NO_CLEAR;                    }                    applyZenModeLocked(r);                    mRankingHelper.sort(mNotificationList);                    if (notification.icon != 0) {                        StatusBarNotification oldSbn = (old != null) ? old.sbn : null;                        mListeners.notifyPostedLocked(n, oldSbn);                    } else {                        Slog.e(TAG, "Not posting notification with icon==0: " + notification);                        if (old != null && !old.isCanceled) {                            mListeners.notifyRemovedLocked(n);                        }                        // ATTENTION: in a future release we will bail out here                        // so that we do not play sounds, show lights, etc. for invalid                        // notifications                        Slog.e(TAG, "WARNING: In a future release this will crash the app: "                                + n.getPackageName());                    }                    buzzBeepBlinkLocked(r);                }            }        });        idOut[0] = id;    } /**         * asynchronously notify all listeners about a new notification         *         * 

* Also takes care of removing a notification that has been visible to a listener before, * but isn't anymore. */ public void notifyPostedLocked(StatusBarNotification sbn, StatusBarNotification oldSbn) { // Lazily initialized snapshots of the notification. StatusBarNotification sbnClone = null; StatusBarNotification sbnCloneLight = null; for (final ManagedServiceInfo info : mServices) { boolean sbnVisible = isVisibleToListener(sbn, info); boolean oldSbnVisible = oldSbn != null ? isVisibleToListener(oldSbn, info) : false; // This notification hasn't been and still isn't visible -> ignore. if (!oldSbnVisible && !sbnVisible) { continue; } final NotificationRankingUpdate update = makeRankingUpdateLocked(info); // This notification became invisible -> remove the old one. if (oldSbnVisible && !sbnVisible) { final StatusBarNotification oldSbnLightClone = oldSbn.cloneLight(); mHandler.post(new Runnable() { @Override public void run() { notifyRemoved(info, oldSbnLightClone, update); } }); continue; } final int trim = mListeners.getOnNotificationPostedTrim(info); if (trim == TRIM_LIGHT && sbnCloneLight == null) { sbnCloneLight = sbn.cloneLight(); } else if (trim == TRIM_FULL && sbnClone == null) { sbnClone = sbn.clone(); } final StatusBarNotification sbnToPost = (trim == TRIM_FULL) ? sbnClone : sbnCloneLight; mHandler.post(new Runnable() { @Override public void run() { notifyPosted(info, sbnToPost, update); } }); } } private void notifyPosted(final ManagedServiceInfo info, final StatusBarNotification sbn, NotificationRankingUpdate rankingUpdate) { final INotificationListener listener = (INotificationListener)info.service; StatusBarNotificationHolder sbnHolder = new StatusBarNotificationHolder(sbn); try { listener.onNotificationPosted(sbnHolder, rankingUpdate); } catch (RemoteException ex) { Log.e(TAG, "unable to notify listener (posted): " + listener, ex); } }

|-- frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java

/**---- 注册监听通知服务 ----**/    public void start() {        // Set up the initial notification state.        try {            mNotificationListener.registerAsSystemService(mContext,                    new ComponentName(mContext.getPackageName(), getClass().getCanonicalName()),                    UserHandle.USER_ALL);        } catch (RemoteException e) {            Log.e(TAG, "Unable to register notification listener", e);        }}|-- frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java```java/**---- 注册监听通知服务 ----**/    public void start() {        // Set up the initial notification state.        try {            mNotificationListener.registerAsSystemService(mContext,                    new ComponentName(mContext.getPackageName(), getClass().getCanonicalName()),                    UserHandle.USER_ALL);        } catch (RemoteException e) {            Log.e(TAG, "Unable to register notification listener", e);        }}    private final NotificationListenerService mNotificationListener =            new NotificationListenerService() {        @Override        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);                    }                }            });        }/**---- 由 NotificationManagerService 调用 ----**/        @Override        public void onNotificationPosted(final StatusBarNotification sbn,                final RankingMap rankingMap) {            if (DEBUG) Log.d(TAG, "onNotificationPosted: " + sbn);            mHandler.post(new Runnable() {                @Override                public void run() {                    Notification n = sbn.getNotification();                    boolean isUpdate = mNotificationData.get(sbn.getKey()) != null                            || isHeadsUp(sbn.getKey());                    // Ignore children of notifications that have a summary, since we're not                    // going to show them anyway. This is true also when the summary is canceled,                    // because children are automatically canceled by NoMan in that case.                    if (n.isGroupChild() &&                            mNotificationData.isGroupWithSummary(sbn.getGroupKey())) {                        if (DEBUG) {                            Log.d(TAG, "Ignoring group child due to existing summary: " + sbn);                        }                        // Remove existing notification to avoid stale data.                        if (isUpdate) {                            removeNotification(sbn.getKey(), rankingMap);                        } else {                            mNotificationData.updateRanking(rankingMap);                        }                        return;                    }                    if (isUpdate) {                        updateNotification(sbn, rankingMap);                    } else {                        addNotification(sbn, rankingMap);                    }                }            });        }        @Override        public void onNotificationRemoved(final StatusBarNotification sbn,                final RankingMap rankingMap) {            if (DEBUG) Log.d(TAG, "onNotificationRemoved: " + sbn);            mHandler.post(new Runnable() {                @Override                public void run() {                    removeNotification(sbn.getKey(), rankingMap);                }            });        }        @Override        public void onNotificationRankingUpdate(final RankingMap rankingMap) {            if (DEBUG) Log.d(TAG, "onRankingUpdate");            mHandler.post(new Runnable() {                @Override                public void run() {                    updateNotificationRanking(rankingMap);                }            });        }    };

|-- frameworks/base/core/java/android/service/notification/NotificationListenerService.java

    /**     * Directly register this service with the Notification Manager.     *     * 

Only system services may use this call. It will fail for non-system callers. * Apps should ask the user to add their listener in Settings. * * @param context Context required for accessing resources. Since this service isn't * launched as a real Service when using this method, a context has to be passed in. * @param componentName the component that will consume the notification information * @param currentUser the user to use as the stream filter * @hide */ @SystemApi public void registerAsSystemService(Context context, ComponentName componentName, int currentUser) throws RemoteException { mSystemContext = context; if (mWrapper == null) { mWrapper = new INotificationListenerWrapper(); } INotificationManager noMan = getNotificationInterface(); noMan.registerListener(mWrapper, componentName, currentUser); mCurrentUser = currentUser; }

|-- frameworks/base/services/core/java/com/android/server/notification/NotificationManagerService.java

        /**         * Register a listener binder directly with the notification manager.         *         * Only works with system callers. Apps should extend         * {@link android.service.notification.NotificationListenerService}.         */        @Override        public void registerListener(final INotificationListener listener,                final ComponentName component, final int userid) {            enforceSystemOrSystemUI("INotificationManager.registerListener");            mListeners.registerService(listener, component, userid);        }

收到通知后的处理:

|-- frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java

    @Override    public void addNotification(StatusBarNotification notification, RankingMap ranking) {        if (DEBUG) Log.d(TAG, "addNotification key=" + notification.getKey());        if (mUseHeadsUp && shouldInterrupt(notification)) {            if (DEBUG) Log.d(TAG, "launching notification in heads up mode");            Entry interruptionCandidate = new Entry(notification, null);            ViewGroup holder = mHeadsUpNotificationView.getHolder();            if (inflateViewsForHeadsUp(interruptionCandidate, holder)) {/**---- 只需注释掉, 即可阻止显示HEADS-UP 通知 ---- **/                // 1. Populate mHeadsUpNotificationView                mHeadsUpNotificationView.showNotification(interruptionCandidate);                // do not show the notification in the shade, yet.                return;            }        }        Entry shadeEntry = createNotificationViews(notification);        if (shadeEntry == null) {            return;        }        if (notification.getNotification().fullScreenIntent != null) {            // Stop screensaver if the notification has a full-screen intent.            // (like an incoming phone call)            awakenDreams();            // not immersive & a full-screen alert should be shown            if (DEBUG) Log.d(TAG, "Notification has fullScreenIntent; sending fullScreenIntent");            try {                EventLog.writeEvent(EventLogTags.SYSUI_FULLSCREEN_NOTIFICATION,                        notification.getKey());                notification.getNotification().fullScreenIntent.send();            } catch (PendingIntent.CanceledException e) {            }        } else {            // usual case: status bar visible & not immersive            // show the ticker if there isn't already a heads up            if (mHeadsUpNotificationView.getEntry() == null) {                tick(notification, true);            }        }        addNotificationViews(shadeEntry, ranking);        // Recalculate the position of the sliding windows and the titles.        setAreThereNotifications();        updateExpandedViewPos(EXPANDED_LEAVE_ALONE);    }

|-- frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java

    protected boolean shouldInterrupt(StatusBarNotification sbn) {        if (mNotificationData.shouldFilterOut(sbn)) {            if (DEBUG) {                Log.d(TAG, "Skipping HUN check for " + sbn.getKey() + " since it's filtered out.");            }            return false;        }        if ((null!=mHeadsUpNotificationView)&&mHeadsUpNotificationView.isSnoozed(sbn.getPackageName())) {            return false;        }        Notification notification = sbn.getNotification();        // some predicates to make the boolean logic legible        boolean isNoisy = (notification.defaults & Notification.DEFAULT_SOUND) != 0                || (notification.defaults & Notification.DEFAULT_VIBRATE) != 0                || notification.sound != null                || notification.vibrate != null;        boolean isHighPriority = sbn.getScore() >= INTERRUPTION_THRESHOLD;/**---- 前面已设置非空 ----**/        boolean isFullscreen = notification.fullScreenIntent != null;        boolean hasTicker = mHeadsUpTicker && !TextUtils.isEmpty(notification.tickerText);        boolean isAllowed = notification.extras.getInt(Notification.EXTRA_AS_HEADS_UP,                Notification.HEADS_UP_ALLOWED) != Notification.HEADS_UP_NEVER;        boolean accessibilityForcesLaunch = isFullscreen                && mAccessibilityManager.isTouchExplorationEnabled();         if(mContext.getResources().getConfiguration().enableMultiWindow()&&!isFullscreen)              isFullscreen = true&&!sbn.isOngoing();        boolean interrupt = (isFullscreen || (isHighPriority && (isNoisy || hasTicker)))                && isAllowed                && !accessibilityForcesLaunch                && mPowerManager.isScreenOn()                && (!mStatusBarKeyguardViewManager.isShowing()                        || mStatusBarKeyguardViewManager.isOccluded())                && !mStatusBarKeyguardViewManager.isInputRestricted();        try {            interrupt = interrupt && !mDreamManager.isDreaming();        } catch (RemoteException e) {            Log.d(TAG, "failed to query dream manager", e);        }        if (DEBUG) Log.d(TAG, "interrupt: " + interrupt);        return interrupt;    }

|-- frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java

    public boolean showNotification(NotificationData.Entry headsUp) {        if (mHeadsUp != null && headsUp != null && !mHeadsUp.key.equals(headsUp.key)) {            // bump any previous heads up back to the shade            release();        }        mHeadsUp = headsUp;        if (mContentHolder != null) {            mContentHolder.removeAllViews();        }        if (mHeadsUp != null) {            mMostRecentPackageName = mHeadsUp.notification.getPackageName();            mHeadsUp.row.setSystemExpanded(true);            mHeadsUp.row.setSensitive(false);            mHeadsUp.row.setHeadsUp(true);            mHeadsUp.row.setHideSensitive(                    false, false /* animated */, 0 /* delay */, 0 /* duration */);            if (mContentHolder == null) {                // too soon!                return false;            }            mContentHolder.setX(0);            mContentHolder.setVisibility(View.VISIBLE);            mContentHolder.setAlpha(mMaxAlpha);            mContentHolder.addView(mHeadsUp.row);            sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);            mSwipeHelper.snapChild(mContentHolder, 1f);            mStartTouchTime = SystemClock.elapsedRealtime() + mTouchSensitivityDelay;            mHeadsUp.setInterruption();            // 2. Animate mHeadsUpNotificationView in            mBar.scheduleHeadsUpOpen();            // 3. Set alarm to age the notification off            mBar.resetHeadsUpDecayTimer();        }        return true;    }

通知长按处理

通知VIEW结构:

|-- frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java|-- frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java|-- frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java... * N

ExpandableNotificationRow 的父类关系:
ExpandableNotificationRow -> ActivatableNotificationView -> ExpandableOutlineView -> ExpandableView -> FrameLayout

长按事件实际是由NotificationStackScrollLayout处理的:
|-- frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java

    public void setLongPressListener(SwipeHelper.LongPressListener listener) {        mSwipeHelper.setLongPressListener(listener);        mLongPressListener = listener;    }

|-- frameworks/base/packages/SystemUI/src/com/android/systemui/SwipeHelper.java

    public void setLongPressListener(LongPressListener listener) {        mLongPressListener = listener;    }    public boolean onInterceptTouchEvent(final MotionEvent ev) {        final int action = ev.getAction();        switch (action) {            case MotionEvent.ACTION_DOWN:                mTouchAboveFalsingThreshold = false;                mDragging = false;                mLongPressSent = false;                mCurrView = mCallback.getChildAtPosition(ev);                mVelocityTracker.clear();                if (mCurrView != null) {                    mCurrAnimView = mCallback.getChildContentView(mCurrView);                    mCanCurrViewBeDimissed = mCallback.canChildBeDismissed(mCurrView);                    mVelocityTracker.addMovement(ev);                    mInitialTouchPos = getPos(ev);                    if (mLongPressListener != null) {                        if (mWatchLongPress == null) {                            mWatchLongPress = new Runnable() {                                @Override                                public void run() {                                    if (mCurrView != null && !mLongPressSent) {                                        mLongPressSent = true;                                        mCurrView.sendAccessibilityEvent(                                                AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);                                        mCurrView.getLocationOnScreen(mTmpPos);                                        final int x = (int) ev.getRawX() - mTmpPos[0];                                        final int y = (int) ev.getRawY() - mTmpPos[1];                                        mLongPressListener.onLongPress(mCurrView, x, y);                                    }                                }                            };                        }                        mHandler.postDelayed(mWatchLongPress, mLongPressTimeout);                    }                }                break;...}

长按的监听由PhoneStatusBar传入:
|-- frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java

    protected PhoneStatusBarView makeStatusBarView() {        final Context context = mContext;        IntentFilter intentfilter=new IntentFilter();        intentfilter.addAction("rk.android.screenshot.SHOW");        intentfilter.addAction("rk.android.screenshot.ACTION");        context.registerReceiver(receiver, intentfilter);...        mStackScroller = (NotificationStackScrollLayout) mStatusBarWindow.findViewById(                R.id.notification_stack_scroller);        mStackScroller.setLongPressListener(getNotificationLongClicker());        mStackScroller.setPhoneStatusBar(this);}

|-- frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java

    protected SwipeHelper.LongPressListener getNotificationLongClicker() {        return new SwipeHelper.LongPressListener() {            @Override            public boolean onLongPress(View v, int x, int y) {/**---- 若不希望处理长按, 则可直接返回结果, 或不注册长按监听即可 ----**/                dismissPopups();                if (!(v instanceof ExpandableNotificationRow)) {                    return false;                }                if (v.getWindowToken() == null) {                    Log.e(TAG, "Trying to show notification guts, but not attached to window");                    return false;                }                inflateGuts((ExpandableNotificationRow) v);                // Assume we are a status_bar_notification_row                final NotificationGuts guts = (NotificationGuts) v.findViewById(                        R.id.notification_guts);                if (guts == null) {                    // This view has no guts. Examples are the more card or the dismiss all view                    return false;                }                // Already showing?                if (guts.getVisibility() == View.VISIBLE) {                    Log.e(TAG, "Trying to show notification guts, but already visible");                    return false;                }                guts.setVisibility(View.VISIBLE);                final double horz = Math.max(guts.getWidth() - x, x);                final double vert = Math.max(guts.getActualHeight() - y, y);                final float r = (float) Math.hypot(horz, vert);                final Animator a                        = ViewAnimationUtils.createCircularReveal(guts, x, y, 0, r);                a.setDuration(400);                a.setInterpolator(mLinearOutSlowIn);                a.start();                mNotificationGutsExposed = guts;                return true;            }        };    }

更多相关文章

  1. android实现关键字搜索功能
  2. Android 获取屏幕高宽度,密度,通知栏高度,截图等常用方法
  3. Android5.0通知变化浅析
  4. Android通知系统源码解析
  5. 系出名门Android(3) - 对话框(Dialog)和通知(Notification)
  6. Android Notification通知栏的必备姿势
  7. Android 通知(Notification)高级用法和注意事项
  8. wifi 通知栏上 选择程序时出现你的应用
  9. android之【本地通知Notification】

随机推荐

  1. Android获取手机信号强度/信号格数
  2. Android中RelativeLayout各个属性的含义
  3. 基于MQTT实现Android消息推送(Push…
  4. Android(安卓)默认壁纸 简单分析
  5. Android(安卓)如何从屏幕底部向上滑出一
  6. Android设置颜色
  7. android onTouchEvent和setOnTouchListen
  8. Android(安卓)Android(安卓)Studio 快捷
  9. Android(安卓)左右侧滑组件
  10. Android(安卓)视频分享 Android(安卓)Stu