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
17package com.android.messaging.datamodel.data;
18
19import android.app.LoaderManager;
20import android.content.Context;
21import android.content.Loader;
22import android.database.Cursor;
23import android.os.Bundle;
24import android.text.TextUtils;
25
26import com.android.messaging.R;
27import com.android.messaging.datamodel.BoundCursorLoader;
28import com.android.messaging.datamodel.DatabaseHelper.ParticipantColumns;
29import com.android.messaging.datamodel.MessagingContentProvider;
30import com.android.messaging.datamodel.binding.BindableData;
31import com.android.messaging.datamodel.binding.BindingBase;
32import com.android.messaging.util.Assert;
33import com.android.messaging.util.LogUtil;
34import com.android.messaging.util.OsUtil;
35
36import java.util.ArrayList;
37import 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 */
43public 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