3232import android .graphics .Bitmap ;
3333import android .graphics .Canvas ;
3434import android .graphics .Matrix ;
35- import android .graphics .Paint ;
36- import android .graphics .RectF ;
3735import android .graphics .Shader .TileMode ;
3836import android .graphics .drawable .BitmapDrawable ;
3937import android .graphics .drawable .Drawable ;
40- import android .graphics .drawable .StateListDrawable ;
4138import android .net .Uri ;
4239import android .os .AsyncTask ;
4340import android .os .Handler ;
5653import android .view .animation .AnimationUtils ;
5754import android .widget .AdapterView ;
5855import android .widget .BaseAdapter ;
59- import android .widget .FrameLayout ;
6056import android .widget .HorizontalScrollView ;
6157import android .widget .ImageView ;
6258import android .widget .PopupMenu ;
@@ -202,6 +198,7 @@ public View getView(int position, View convertView, ViewGroup parent) {
202198 holder .descriptionView .setText (activityDescription .recentTaskInfo .description );
203199 holder .thumbnailView .setTag (activityDescription );
204200 holder .thumbnailView .setOnLongClickListener (new OnLongClickDelegate (convertView ));
201+ holder .thumbnailView .setContentDescription (activityDescription .getLabel ());
205202 holder .activityDescription = activityDescription ;
206203
207204 return convertView ;
@@ -228,6 +225,23 @@ public boolean isInContentArea(int x, int y) {
228225 }
229226
230227 public void show (boolean show , boolean animate ) {
228+ if (show ) {
229+ // Need to update list of recent apps before we set visibility so this view's
230+ // content description is updated before it gets focus for TalkBack mode
231+ refreshApplicationList ();
232+
233+ // if there are no apps, either bring up a "No recent apps" message, or just
234+ // quit early
235+ boolean noApps = (mActivityDescriptions .size () == 0 );
236+ if (mRecentsNoApps != null ) { // doesn't exist on large devices
237+ mRecentsNoApps .setVisibility (noApps ? View .VISIBLE : View .INVISIBLE );
238+ } else {
239+ if (noApps ) {
240+ if (DEBUG ) Log .v (TAG , "Nothing to show" );
241+ return ;
242+ }
243+ }
244+ }
231245 if (animate ) {
232246 if (mShowing != show ) {
233247 mShowing = show ;
@@ -378,11 +392,13 @@ protected void onFinishInflate() {
378392 mRecentsNoApps = findViewById (R .id .recents_no_apps );
379393 mChoreo = new Choreographer (this , mRecentsScrim , mRecentsGlowView , mRecentsNoApps , this );
380394 mRecentsDismissButton = findViewById (R .id .recents_dismiss_button );
381- mRecentsDismissButton .setOnClickListener (new OnClickListener () {
382- public void onClick (View v ) {
383- hide (true );
384- }
385- });
395+ if (mRecentsDismissButton != null ) {
396+ mRecentsDismissButton .setOnClickListener (new OnClickListener () {
397+ public void onClick (View v ) {
398+ hide (true );
399+ }
400+ });
401+ }
386402
387403 // In order to save space, we make the background texture repeat in the Y direction
388404 if (mRecentsScrim != null && mRecentsScrim .getBackground () instanceof BitmapDrawable ) {
@@ -400,9 +416,6 @@ private void createCustomAnimations(LayoutTransition transitioner) {
400416 protected void onVisibilityChanged (View changedView , int visibility ) {
401417 super .onVisibilityChanged (changedView , visibility );
402418 if (DEBUG ) Log .v (TAG , "onVisibilityChanged(" + changedView + ", " + visibility + ")" );
403- if (visibility == View .VISIBLE && changedView == this ) {
404- refreshApplicationList ();
405- }
406419
407420 if (mRecentsContainer instanceof RecentsHorizontalScrollView ) {
408421 ((RecentsHorizontalScrollView ) mRecentsContainer ).onRecentsVisibilityChanged ();
@@ -553,6 +566,7 @@ void applyActivityDescription(ActivityDescription ad, int index, boolean anim) {
553566 }
554567 h .iconView .setVisibility (View .VISIBLE );
555568 h .labelView .setText (ad .getLabel ());
569+ h .thumbnailView .setContentDescription (ad .getLabel ());
556570 if (anim ) {
557571 h .labelView .setAnimation (AnimationUtils .loadAnimation (
558572 mContext , R .anim .recent_appear ));
@@ -582,10 +596,18 @@ private void refreshApplicationList() {
582596 mThumbnailLoader .cancel (false );
583597 mThumbnailLoader = null ;
584598 }
585- if (mRecentsNoApps != null ) { // doesn't exist on large devices
586- mRecentsNoApps .setVisibility (View .INVISIBLE );
587- }
599+
588600 mActivityDescriptions = getRecentTasks ();
601+ int numRecentApps = mActivityDescriptions .size ();
602+ String recentAppsAccessibilityDescription ;
603+ if (numRecentApps == 0 ) {
604+ recentAppsAccessibilityDescription =
605+ getResources ().getString (R .string .status_bar_no_recent_apps );
606+ } else {
607+ recentAppsAccessibilityDescription = getResources ().getQuantityString (
608+ R .plurals .status_bar_accessibility_recent_apps , numRecentApps , numRecentApps );
609+ }
610+ setContentDescription (recentAppsAccessibilityDescription );
589611 for (ActivityDescription ad : mActivityDescriptions ) {
590612 ad .setThumbnail (mDefaultThumbnailBackground );
591613 }
@@ -649,14 +671,6 @@ protected Void doInBackground(Void... params) {
649671 };
650672 mThumbnailLoader .executeOnExecutor (AsyncTask .THREAD_POOL_EXECUTOR );
651673 }
652- } else {
653- // Immediately hide this panel
654- if (DEBUG ) Log .v (TAG , "Nothing to show" );
655- if (mRecentsNoApps != null ) { // doesn't exist on large devices
656- mRecentsNoApps .setVisibility (View .VISIBLE );
657- } else {
658- hide (false );
659- }
660674 }
661675 }
662676
0 commit comments