1 /* 2 * Copyright (C) 2015 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.messaging.datamodel.data; 18 19 import android.app.LoaderManager; 20 import android.content.Context; 21 import android.content.Loader; 22 import android.database.Cursor; 23 import android.os.Bundle; 24 import android.text.TextUtils; 25 26 import com.android.messaging.R; 27 import com.android.messaging.datamodel.BoundCursorLoader; 28 import com.android.messaging.datamodel.DatabaseHelper.ParticipantColumns; 29 import com.android.messaging.datamodel.MessagingContentProvider; 30 import com.android.messaging.datamodel.binding.BindableData; 31 import com.android.messaging.datamodel.binding.BindingBase; 32 import com.android.messaging.util.Assert; 33 import com.android.messaging.util.LogUtil; 34 import com.android.messaging.util.OsUtil; 35 36 import java.util.ArrayList; 37 import java.util.List; 38 39 /** 40 * Services SettingsFragment's data needs for loading active self participants to display 41 * the list of active subscriptions. 42 */ 43 public class SettingsData extends BindableData implements 44 LoaderManager.LoaderCallbacks<Cursor> { 45 public interface SettingsDataListener { 46 void onSelfParticipantDataLoaded(SettingsData data); 47 } 48 49 public static class SettingsItem { 50 public static final int TYPE_GENERAL_SETTINGS = 1; 51 public static final int TYPE_PER_SUBSCRIPTION_SETTINGS = 2; 52 53 private final String mDisplayName; 54 private final String mDisplayDetail; 55 private final String mActivityTitle; 56 private final int mType; 57 private final int mSubId; 58 59 private SettingsItem(final String displayName, final String displayDetail, 60 final String activityTitle, final int type, final int subId) { 61 mDisplayName = displayName; 62 mDisplayDetail = displayDetail; 63 mActivityTitle = activityTitle; 64 mType = type; 65 mSubId = subId; 66 } 67 68 public String getDisplayName() { 69 return mDisplayName; 70 } 71 72 public String getDisplayDetail() { 73 return mDisplayDetail; 74 } 75 76 public int getType() { 77 return mType; 78 } 79 80 public int getSubId() { 81 return mSubId; 82 } 83 84 public String getActivityTitle() { 85 return mActivityTitle; 86 } 87 88 public static SettingsItem fromSelfParticipant(final Context context, 89 final ParticipantData self) { 90 Assert.isTrue(self.isSelf()); 91 Assert.isTrue(self.isActiveSubscription()); 92 final String displayDetail = TextUtils.isEmpty(self.getDisplayDestination()) ? 93 context.getString(R.string.sim_settings_unknown_number) : 94 self.getDisplayDestination(); 95 final String displayName = context.getString(R.string.sim_specific_settings, 96 self.getSubscriptionName()); 97 return new SettingsItem(displayName, displayDetail, displayName, 98 TYPE_PER_SUBSCRIPTION_SETTINGS, self.getSubId()); 99 } 100 101 public static SettingsItem createGeneralSettingsItem(final Context context) { 102 return new SettingsItem(context.getString(R.string.general_settings), 103 null, context.getString(R.string.general_settings_activity_title), 104 TYPE_GENERAL_SETTINGS, -1); 105 } 106 107 public static SettingsItem createDefaultMmsSettingsItem(final Context context, 108 final int subId) { 109 return new SettingsItem(context.getString(R.string.advanced_settings), 110 null, context.getString(R.string.advanced_settings_activity_title), 111 TYPE_PER_SUBSCRIPTION_SETTINGS, subId); 112 } 113 } 114 115 private static final String BINDING_ID = "bindingId"; 116 private final Context mContext; 117 private final SelfParticipantsData mSelfParticipantsData; 118 private LoaderManager mLoaderManager; 119 private SettingsDataListener mListener; 120 121 public SettingsData(final Context context, 122 final SettingsDataListener listener) { 123 mListener = listener; 124 mContext = context; 125 mSelfParticipantsData = new SelfParticipantsData(); 126 } 127 128 private static final int SELF_PARTICIPANT_LOADER = 1; 129 130 @Override 131 public Loader<Cursor> onCreateLoader(final int id, final Bundle args) { 132 Assert.equals(SELF_PARTICIPANT_LOADER, id); 133 Loader<Cursor> loader = null; 134 135 final String bindingId = args.getString(BINDING_ID); 136 // Check if data still bound to the requesting ui element 137 if (isBound(bindingId)) { 138 loader = new BoundCursorLoader(bindingId, mContext, 139 MessagingContentProvider.PARTICIPANTS_URI, 140 ParticipantData.ParticipantsQuery.PROJECTION, 141 ParticipantColumns.SUB_ID + " <> ?", 142 new String[] { String.valueOf(ParticipantData.OTHER_THAN_SELF_SUB_ID) }, 143 null); 144 } else { 145 LogUtil.w(LogUtil.BUGLE_TAG, "Creating self loader after unbinding"); 146 } 147 return loader; 148 } 149 150 @Override 151 public void onLoadFinished(final Loader<Cursor> generic, final Cursor data) { 152 final BoundCursorLoader loader = (BoundCursorLoader) generic; 153 154 // Check if data still bound to the requesting ui element 155 if (isBound(loader.getBindingId())) { 156 mSelfParticipantsData.bind(data); 157 mListener.onSelfParticipantDataLoaded(this); 158 } else { 159 LogUtil.w(LogUtil.BUGLE_TAG, "Self loader finished after unbinding"); 160 } 161 } 162 163 @Override 164 public void onLoaderReset(final Loader<Cursor> generic) { 165 final BoundCursorLoader loader = (BoundCursorLoader) generic; 166 167 // Check if data still bound to the requesting ui element 168 if (isBound(loader.getBindingId())) { 169 mSelfParticipantsData.bind(null); 170 } else { 171 LogUtil.w(LogUtil.BUGLE_TAG, "Self loader reset after unbinding"); 172 } 173 } 174 175 public void init(final LoaderManager loaderManager, 176 final BindingBase<SettingsData> binding) { 177 final Bundle args = new Bundle(); 178 args.putString(BINDING_ID, binding.getBindingId()); 179 mLoaderManager = loaderManager; 180 mLoaderManager.initLoader(SELF_PARTICIPANT_LOADER, args, this); 181 } 182 183 @Override 184 protected void unregisterListeners() { 185 mListener = null; 186 187 // This could be null if we bind but the caller doesn't init the BindableData 188 if (mLoaderManager != null) { 189 mLoaderManager.destroyLoader(SELF_PARTICIPANT_LOADER); 190 mLoaderManager = null; 191 } 192 } 193 194 public List<SettingsItem> getSettingsItems() { 195 final List<ParticipantData> selfs = mSelfParticipantsData.getSelfParticipants(true); 196 final List<SettingsItem> settingsItems = new ArrayList<SettingsItem>(); 197 // First goes the general settings, followed by per-subscription settings. 198 settingsItems.add(SettingsItem.createGeneralSettingsItem(mContext)); 199 // For per-subscription settings, show the actual SIM name with phone number if the 200 // platorm is at least L-MR1 and there are multiple active SIMs. 201 final int activeSubCountExcludingDefault = 202 mSelfParticipantsData.getSelfParticipantsCountExcludingDefault(true); 203 if (OsUtil.isAtLeastL_MR1() && activeSubCountExcludingDefault > 0) { 204 for (ParticipantData self : selfs) { 205 if (!self.isDefaultSelf()) { 206 if (activeSubCountExcludingDefault > 1) { 207 settingsItems.add(SettingsItem.fromSelfParticipant(mContext, self)); 208 } else { 209 // This is the only active non-default SIM. 210 settingsItems.add(SettingsItem.createDefaultMmsSettingsItem(mContext, 211 self.getSubId())); 212 break; 213 } 214 } 215 } 216 } else { 217 // Either pre-L-MR1, or there's no active SIM, so show the default MMS settings. 218 settingsItems.add(SettingsItem.createDefaultMmsSettingsItem(mContext, 219 ParticipantData.DEFAULT_SELF_SUB_ID)); 220 } 221 return settingsItems; 222 } 223 } 224