1 /* 2 * Copyright (C) 2013 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.settings; 18 19 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; 20 21 import android.content.ComponentName; 22 import android.content.Context; 23 import android.content.DialogInterface; 24 import android.content.Intent; 25 import android.content.pm.ApplicationInfo; 26 import android.content.pm.PackageManager; 27 import android.graphics.drawable.Drawable; 28 import android.os.Bundle; 29 import android.provider.Telephony.Sms.Intents; 30 import android.telephony.TelephonyManager; 31 import android.text.TextUtils; 32 import android.view.LayoutInflater; 33 import android.view.View; 34 import android.view.ViewGroup; 35 import android.view.Window; 36 import android.view.WindowManager; 37 import android.widget.BaseAdapter; 38 import android.widget.ImageView; 39 import android.widget.TextView; 40 41 import com.android.internal.app.AlertActivity; 42 import com.android.internal.app.AlertController; 43 import com.android.internal.telephony.SmsApplication; 44 import com.android.internal.telephony.SmsApplication.SmsApplicationData; 45 46 import java.util.ArrayList; 47 import java.util.List; 48 49 public final class SmsDefaultDialog extends AlertActivity implements 50 DialogInterface.OnClickListener { 51 private SmsApplicationData mNewSmsApplicationData; 52 53 @Override onCreate(Bundle savedInstanceState)54 protected void onCreate(Bundle savedInstanceState) { 55 super.onCreate(savedInstanceState); 56 57 Intent intent = getIntent(); 58 String packageName = intent.getStringExtra(Intents.EXTRA_PACKAGE_NAME); 59 60 setResult(RESULT_CANCELED); 61 if (!buildDialog(packageName)) { 62 finish(); 63 } 64 } 65 66 @Override onStart()67 protected void onStart() { 68 super.onStart(); 69 getWindow().addPrivateFlags(PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); 70 android.util.EventLog.writeEvent(0x534e4554, "120484087", -1, ""); 71 } 72 73 @Override onStop()74 protected void onStop() { 75 super.onStop(); 76 final Window window = getWindow(); 77 final WindowManager.LayoutParams attrs = window.getAttributes(); 78 attrs.privateFlags &= ~PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; 79 window.setAttributes(attrs); 80 } 81 82 @Override onClick(DialogInterface dialog, int which)83 public void onClick(DialogInterface dialog, int which) { 84 switch (which) { 85 case BUTTON_POSITIVE: 86 SmsApplication.setDefaultApplication(mNewSmsApplicationData.mPackageName, this); 87 setResult(RESULT_OK); 88 break; 89 case BUTTON_NEGATIVE: 90 break; 91 default: 92 if (which >= 0) { 93 AppListAdapter adapter = (AppListAdapter) mAlertParams.mAdapter; 94 if (!adapter.isSelected(which)) { 95 String packageName = adapter.getPackageName(which); 96 if (!TextUtils.isEmpty(packageName)) { 97 SmsApplication.setDefaultApplication(packageName, this); 98 setResult(RESULT_OK); 99 } 100 } 101 } 102 break; 103 } 104 } 105 buildDialog(String packageName)106 private boolean buildDialog(String packageName) { 107 TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); 108 if (!tm.isSmsCapable()) { 109 // No phone, no SMS 110 return false; 111 } 112 final AlertController.AlertParams p = mAlertParams; 113 p.mTitle = getString(R.string.sms_change_default_dialog_title); 114 mNewSmsApplicationData = SmsApplication.getSmsApplicationData(packageName, this); 115 if (mNewSmsApplicationData != null) { 116 // New default SMS app specified, change to that directly after the confirmation 117 // dialog. 118 SmsApplicationData oldSmsApplicationData = null; 119 ComponentName oldSmsComponent = SmsApplication.getDefaultSmsApplication(this, true); 120 if (oldSmsComponent != null) { 121 oldSmsApplicationData = SmsApplication.getSmsApplicationData( 122 oldSmsComponent.getPackageName(), this); 123 if (oldSmsApplicationData.mPackageName.equals( 124 mNewSmsApplicationData.mPackageName)) { 125 return false; 126 } 127 } 128 129 // Compose dialog; get 130 if (oldSmsApplicationData != null) { 131 p.mMessage = getString(R.string.sms_change_default_dialog_text, 132 mNewSmsApplicationData.getApplicationName(this), 133 oldSmsApplicationData.getApplicationName(this)); 134 } else { 135 p.mMessage = getString(R.string.sms_change_default_no_previous_dialog_text, 136 mNewSmsApplicationData.getApplicationName(this)); 137 } 138 p.mPositiveButtonText = getString(R.string.yes); 139 p.mNegativeButtonText = getString(R.string.no); 140 p.mPositiveButtonListener = this; 141 p.mNegativeButtonListener = this; 142 } else { 143 // No new default SMS app specified, show a list of all SMS apps and let user to pick 144 p.mAdapter = new AppListAdapter(); 145 p.mOnClickListener = this; 146 p.mNegativeButtonText = getString(R.string.cancel); 147 p.mNegativeButtonListener = this; 148 if (p.mAdapter.isEmpty()) { 149 // If there is nothing to choose from, don't build the dialog. 150 return false; 151 } 152 } 153 setupAlert(); 154 155 return true; 156 } 157 158 /** 159 * The list of SMS apps with label, icon. Current default SMS app is marked as "default". 160 */ 161 private class AppListAdapter extends BaseAdapter { 162 /** 163 * SMS app item in the list 164 */ 165 private class Item { 166 final String label; // app label 167 final Drawable icon; // app icon 168 final String packgeName; // full app package name 169 Item(String label, Drawable icon, String packageName)170 public Item(String label, Drawable icon, String packageName) { 171 this.label = label; 172 this.icon = icon; 173 this.packgeName = packageName; 174 } 175 } 176 177 // The list 178 private final List<Item> mItems; 179 // The index of selected 180 private final int mSelectedIndex; 181 AppListAdapter()182 public AppListAdapter() { 183 mItems = getItems(); 184 int selected = getSelectedIndex(); 185 // Move selected up to the top so it is easy to find 186 if (selected > 0) { 187 Item item = mItems.remove(selected); 188 mItems.add(0, item); 189 selected = 0; 190 } 191 mSelectedIndex = selected; 192 } 193 194 @Override getCount()195 public int getCount() { 196 return mItems != null ? mItems.size() : 0; 197 } 198 199 @Override getItem(int position)200 public Object getItem(int position) { 201 return mItems != null && position < mItems.size() ? mItems.get(position) : null; 202 } 203 204 @Override getItemId(int position)205 public long getItemId(int position) { 206 return position; 207 } 208 209 @Override getView(int position, View convertView, ViewGroup parent)210 public View getView(int position, View convertView, ViewGroup parent) { 211 Item item = ((Item) getItem(position)); 212 LayoutInflater inflater = getLayoutInflater(); 213 View view = inflater.inflate(R.layout.app_preference_item, parent, false); 214 TextView textView = (TextView) view.findViewById(android.R.id.title); 215 textView.setText(item.label); 216 if (position == mSelectedIndex) { 217 view.findViewById(R.id.default_label).setVisibility(View.VISIBLE); 218 } else { 219 view.findViewById(R.id.default_label).setVisibility(View.GONE); 220 } 221 ImageView imageView = (ImageView) view.findViewById(android.R.id.icon); 222 imageView.setImageDrawable(item.icon); 223 return view; 224 } 225 226 /** 227 * Get the selected package name by 228 * 229 * @param position the index of the item in the list 230 * @return the package name of selected item 231 */ getPackageName(int position)232 public String getPackageName(int position) { 233 Item item = (Item) getItem(position); 234 if (item != null) { 235 return item.packgeName; 236 } 237 return null; 238 } 239 240 /** 241 * Check if an item at a position is already selected 242 * 243 * @param position the index of the item in the list 244 * @return true if the item at the position is already selected, false otherwise 245 */ isSelected(int position)246 public boolean isSelected(int position) { 247 return position == mSelectedIndex; 248 } 249 250 // Get the list items by looking for SMS apps getItems()251 private List<Item> getItems() { 252 PackageManager pm = getPackageManager(); 253 List<Item> items = new ArrayList<>(); 254 for (SmsApplication.SmsApplicationData app : 255 SmsApplication.getApplicationCollection(SmsDefaultDialog.this)) { 256 try { 257 String packageName = app.mPackageName; 258 ApplicationInfo appInfo = pm.getApplicationInfo(packageName, 0/*flags*/); 259 if (appInfo != null) { 260 items.add(new Item( 261 appInfo.loadLabel(pm).toString(), 262 appInfo.loadIcon(pm), 263 packageName)); 264 } 265 } catch (PackageManager.NameNotFoundException e) { 266 // Ignore package can't be found 267 } 268 } 269 return items; 270 } 271 272 // Get the selected item index by looking for the current default SMS app getSelectedIndex()273 private int getSelectedIndex() { 274 ComponentName appName = SmsApplication.getDefaultSmsApplication( 275 SmsDefaultDialog.this, true); 276 if (appName != null) { 277 String defaultSmsAppPackageName = appName.getPackageName(); 278 if (!TextUtils.isEmpty(defaultSmsAppPackageName)) { 279 for (int i = 0; i < mItems.size(); i++) { 280 if (TextUtils.equals(mItems.get(i).packgeName, defaultSmsAppPackageName)) { 281 return i; 282 } 283 } 284 } 285 } 286 return -1; 287 } 288 } 289 } 290