1 /* 2 * Copyright (C) 2017 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 com.android.systemui; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.content.Context; 22 import android.content.DialogInterface; 23 import android.content.Intent; 24 import android.content.pm.ApplicationInfo; 25 import android.content.pm.PackageManager; 26 import android.net.Uri; 27 import android.os.Bundle; 28 import android.provider.Settings; 29 import android.util.IconDrawableFactory; 30 import android.util.Log; 31 import android.view.LayoutInflater; 32 import android.view.View; 33 import android.view.ViewGroup; 34 import android.widget.AdapterView; 35 import android.widget.ArrayAdapter; 36 import android.widget.ImageView; 37 import android.widget.ListView; 38 import android.widget.TextView; 39 40 import com.android.internal.app.AlertActivity; 41 import com.android.internal.app.AlertController; 42 import com.android.internal.logging.MetricsLogger; 43 import com.android.internal.logging.nano.MetricsProto; 44 45 import com.android.systemui.R; 46 47 import java.util.ArrayList; 48 49 /** 50 * Show a list of currently running foreground services (supplied by the caller) 51 * that the user can tap through to their application details. 52 */ 53 public final class ForegroundServicesDialog extends AlertActivity implements 54 AdapterView.OnItemSelectedListener, DialogInterface.OnClickListener, 55 AlertController.AlertParams.OnPrepareListViewListener { 56 57 private static final String TAG = "ForegroundServicesDialog"; 58 59 LayoutInflater mInflater; 60 61 private MetricsLogger mMetricsLogger; 62 63 private String[] mPackages; 64 private PackageItemAdapter mAdapter; 65 66 private DialogInterface.OnClickListener mAppClickListener = 67 new DialogInterface.OnClickListener() { 68 public void onClick(DialogInterface dialog, int which) { 69 String pkg = mAdapter.getItem(which).packageName; 70 Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); 71 intent.setData(Uri.fromParts("package", pkg, null)); 72 startActivity(intent); 73 finish(); 74 } 75 }; 76 77 @Override onCreate(Bundle savedInstanceState)78 protected void onCreate(Bundle savedInstanceState) { 79 super.onCreate(savedInstanceState); 80 Dependency.initDependencies(getApplicationContext()); 81 82 mMetricsLogger = Dependency.get(MetricsLogger.class); 83 84 mInflater = LayoutInflater.from(this); 85 86 mAdapter = new PackageItemAdapter(this); 87 88 final AlertController.AlertParams p = mAlertParams; 89 p.mAdapter = mAdapter; 90 p.mOnClickListener = mAppClickListener; 91 p.mCustomTitleView = mInflater.inflate(R.layout.foreground_service_title, null); 92 p.mIsSingleChoice = true; 93 p.mOnItemSelectedListener = this; 94 p.mPositiveButtonText = getString(com.android.internal.R.string.done_label); 95 p.mPositiveButtonListener = this; 96 p.mOnPrepareListViewListener = this; 97 98 updateApps(getIntent()); 99 if (mPackages == null) { 100 Log.w(TAG, "No packages supplied"); 101 finish(); 102 return; 103 } 104 105 setupAlert(); 106 } 107 108 @Override onResume()109 protected void onResume() { 110 super.onResume(); 111 mMetricsLogger.visible(MetricsProto.MetricsEvent.RUNNING_BACKGROUND_APPS_DIALOG); 112 } 113 114 @Override onPause()115 protected void onPause() { 116 super.onPause(); 117 mMetricsLogger.hidden(MetricsProto.MetricsEvent.RUNNING_BACKGROUND_APPS_DIALOG); 118 } 119 120 @Override onNewIntent(Intent intent)121 protected void onNewIntent(Intent intent) { 122 super.onNewIntent(intent); 123 updateApps(intent); 124 } 125 126 @Override onStop()127 protected void onStop() { 128 super.onStop(); 129 130 // This is a transient dialog, if the user leaves it then it goes away, 131 // they can return back to it from the notification. 132 if (!isChangingConfigurations()) { 133 finish(); 134 } 135 } 136 updateApps(Intent intent)137 void updateApps(Intent intent) { 138 mPackages = intent.getStringArrayExtra("packages"); 139 if (mPackages != null) { 140 mAdapter.setPackages(mPackages); 141 } 142 } 143 onPrepareListView(ListView listView)144 public void onPrepareListView(ListView listView) { 145 } 146 147 /* 148 * On click of Ok/Cancel buttons 149 */ onClick(DialogInterface dialog, int which)150 public void onClick(DialogInterface dialog, int which) { 151 finish(); 152 } 153 onItemSelected(AdapterView parent, View view, int position, long id)154 public void onItemSelected(AdapterView parent, View view, int position, long id) { 155 } 156 onNothingSelected(AdapterView parent)157 public void onNothingSelected(AdapterView parent) { 158 } 159 160 static private class PackageItemAdapter extends ArrayAdapter<ApplicationInfo> { 161 final PackageManager mPm; 162 final LayoutInflater mInflater; 163 final IconDrawableFactory mIconDrawableFactory; 164 PackageItemAdapter(Context context)165 public PackageItemAdapter(Context context) { 166 super(context, R.layout.foreground_service_item); 167 mPm = context.getPackageManager(); 168 mInflater = LayoutInflater.from(context); 169 mIconDrawableFactory = IconDrawableFactory.newInstance(context, true); 170 } 171 setPackages(String[] packages)172 public void setPackages(String[] packages) { 173 clear(); 174 175 ArrayList<ApplicationInfo> apps = new ArrayList<>(); 176 for (int i = 0; i < packages.length; i++) { 177 try { 178 apps.add(mPm.getApplicationInfo(packages[i], 179 PackageManager.MATCH_KNOWN_PACKAGES)); 180 } catch (PackageManager.NameNotFoundException e) { 181 } 182 } 183 184 apps.sort(new ApplicationInfo.DisplayNameComparator(mPm)); 185 addAll(apps); 186 } 187 188 public @NonNull getView(int position, @Nullable View convertView, @NonNull ViewGroup parent)189 View getView(int position, @Nullable View convertView, 190 @NonNull ViewGroup parent) { 191 final View view; 192 if (convertView == null) { 193 view = mInflater.inflate(R.layout.foreground_service_item, parent, false); 194 } else { 195 view = convertView; 196 } 197 198 ImageView icon = view.findViewById(R.id.app_icon); 199 icon.setImageDrawable(mIconDrawableFactory.getBadgedIcon(getItem(position))); 200 201 TextView label = view.findViewById(R.id.app_name); 202 label.setText(getItem(position).loadLabel(mPm)); 203 204 return view; 205 } 206 } 207 } 208