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 {
onSelfParticipantDataLoaded(SettingsData data)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 
SettingsItem(final String displayName, final String displayDetail, final String activityTitle, final int type, final int subId)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 
getDisplayName()68         public String getDisplayName() {
69             return mDisplayName;
70         }
71 
getDisplayDetail()72         public String getDisplayDetail() {
73             return mDisplayDetail;
74         }
75 
getType()76         public int getType() {
77             return mType;
78         }
79 
getSubId()80         public int getSubId() {
81             return mSubId;
82         }
83 
getActivityTitle()84         public String getActivityTitle() {
85             return mActivityTitle;
86         }
87 
fromSelfParticipant(final Context context, final ParticipantData self)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 
createGeneralSettingsItem(final Context context)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 
createDefaultMmsSettingsItem(final Context context, final int subId)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 
SettingsData(final Context context, final SettingsDataListener listener)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
onCreateLoader(final int id, final Bundle args)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
onLoadFinished(final Loader<Cursor> generic, final Cursor data)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
onLoaderReset(final Loader<Cursor> generic)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 
init(final LoaderManager loaderManager, final BindingBase<SettingsData> binding)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
unregisterListeners()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 
getSettingsItems()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