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;
18
19import android.content.Context;
20import android.database.sqlite.SQLiteDatabase;
21import android.net.Uri;
22import android.telephony.SubscriptionManager;
23
24import com.android.messaging.datamodel.action.ActionService;
25import com.android.messaging.datamodel.action.BackgroundWorker;
26import com.android.messaging.datamodel.action.FixupMessageStatusOnStartupAction;
27import com.android.messaging.datamodel.action.ProcessPendingMessagesAction;
28import com.android.messaging.datamodel.data.BlockedParticipantsData;
29import com.android.messaging.datamodel.data.BlockedParticipantsData.BlockedParticipantsDataListener;
30import com.android.messaging.datamodel.data.ContactListItemData;
31import com.android.messaging.datamodel.data.ContactPickerData;
32import com.android.messaging.datamodel.data.ContactPickerData.ContactPickerDataListener;
33import com.android.messaging.datamodel.data.ConversationData;
34import com.android.messaging.datamodel.data.ConversationData.ConversationDataListener;
35import com.android.messaging.datamodel.data.ConversationListData;
36import com.android.messaging.datamodel.data.ConversationListData.ConversationListDataListener;
37import com.android.messaging.datamodel.data.DraftMessageData;
38import com.android.messaging.datamodel.data.GalleryGridItemData;
39import com.android.messaging.datamodel.data.LaunchConversationData;
40import com.android.messaging.datamodel.data.LaunchConversationData.LaunchConversationDataListener;
41import com.android.messaging.datamodel.data.MediaPickerData;
42import com.android.messaging.datamodel.data.MessagePartData;
43import com.android.messaging.datamodel.data.ParticipantData;
44import com.android.messaging.datamodel.data.ParticipantListItemData;
45import com.android.messaging.datamodel.data.PeopleAndOptionsData;
46import com.android.messaging.datamodel.data.PeopleAndOptionsData.PeopleAndOptionsDataListener;
47import com.android.messaging.datamodel.data.PeopleOptionsItemData;
48import com.android.messaging.datamodel.data.SettingsData;
49import com.android.messaging.datamodel.data.SettingsData.SettingsDataListener;
50import com.android.messaging.datamodel.data.SubscriptionListData;
51import com.android.messaging.datamodel.data.VCardContactItemData;
52import com.android.messaging.sms.MmsConfig;
53import com.android.messaging.util.Assert;
54import com.android.messaging.util.Assert.DoesNotRunOnMainThread;
55import com.android.messaging.util.ConnectivityUtil;
56import com.android.messaging.util.LogUtil;
57import com.android.messaging.util.OsUtil;
58import com.android.messaging.util.PhoneUtils;
59
60public class DataModelImpl extends DataModel {
61    private final Context mContext;
62    private final ActionService mActionService;
63    private final BackgroundWorker mDataModelWorker;
64    private final DatabaseHelper mDatabaseHelper;
65    private final ConnectivityUtil mConnectivityUtil;
66    private final SyncManager mSyncManager;
67
68    public DataModelImpl(final Context context) {
69        super();
70        mContext = context;
71        mActionService = new ActionService();
72        mDataModelWorker = new BackgroundWorker();
73        mDatabaseHelper = DatabaseHelper.getInstance(context);
74        mConnectivityUtil = new ConnectivityUtil(context);
75        mSyncManager = new SyncManager();
76    }
77
78    @Override
79    public ConversationListData createConversationListData(final Context context,
80            final ConversationListDataListener listener, final boolean archivedMode) {
81        return new ConversationListData(context, listener, archivedMode);
82    }
83
84    @Override
85    public ConversationData createConversationData(final Context context,
86            final ConversationDataListener listener, final String conversationId) {
87        return new ConversationData(context, listener, conversationId);
88    }
89
90    @Override
91    public ContactListItemData createContactListItemData() {
92        return new ContactListItemData();
93    }
94
95    @Override
96    public ContactPickerData createContactPickerData(final Context context,
97            final ContactPickerDataListener listener) {
98        return new ContactPickerData(context, listener);
99    }
100
101    @Override
102    public BlockedParticipantsData createBlockedParticipantsData(
103            final Context context, final BlockedParticipantsDataListener listener) {
104        return new BlockedParticipantsData(context, listener);
105    }
106
107    @Override
108    public MediaPickerData createMediaPickerData(final Context context) {
109        return new MediaPickerData(context);
110    }
111
112    @Override
113    public GalleryGridItemData createGalleryGridItemData() {
114        return new GalleryGridItemData();
115    }
116
117    @Override
118    public LaunchConversationData createLaunchConversationData(
119            final LaunchConversationDataListener listener) {
120       return new LaunchConversationData(listener);
121    }
122
123    @Override
124    public PeopleOptionsItemData createPeopleOptionsItemData(final Context context) {
125        return new PeopleOptionsItemData(context);
126    }
127
128    @Override
129    public PeopleAndOptionsData createPeopleAndOptionsData(final String conversationId,
130            final Context context, final PeopleAndOptionsDataListener listener) {
131        return new PeopleAndOptionsData(conversationId, context, listener);
132    }
133
134    @Override
135    public VCardContactItemData createVCardContactItemData(final Context context,
136            final MessagePartData data) {
137        return new VCardContactItemData(context, data);
138    }
139
140    @Override
141    public VCardContactItemData createVCardContactItemData(final Context context,
142            final Uri vCardUri) {
143        return new VCardContactItemData(context, vCardUri);
144    }
145
146    @Override
147    public ParticipantListItemData createParticipantListItemData(
148            final ParticipantData participant) {
149        return new ParticipantListItemData(participant);
150    }
151
152    @Override
153    public SubscriptionListData createSubscriptonListData(Context context) {
154        return new SubscriptionListData(context);
155    }
156
157    @Override
158    public SettingsData createSettingsData(Context context, SettingsDataListener listener) {
159        return new SettingsData(context, listener);
160    }
161
162    @Override
163    public DraftMessageData createDraftMessageData(String conversationId) {
164        return new DraftMessageData(conversationId);
165    }
166
167    @Override
168    public ActionService getActionService() {
169        // We need to allow access to this on the UI thread since it's used to start actions.
170        return mActionService;
171    }
172
173    @Override
174    public BackgroundWorker getBackgroundWorkerForActionService() {
175        return mDataModelWorker;
176    }
177
178    @Override
179    @DoesNotRunOnMainThread
180    public DatabaseWrapper getDatabase() {
181        // We prevent the main UI thread from accessing the database since we have to allow
182        // public access to this class to enable sub-packages to access data.
183        Assert.isNotMainThread();
184        return mDatabaseHelper.getDatabase();
185    }
186
187    @Override
188    public ConnectivityUtil getConnectivityUtil() {
189        return mConnectivityUtil;
190    }
191
192    @Override
193    public SyncManager getSyncManager() {
194        return mSyncManager;
195    }
196
197    @Override
198    void onCreateTables(final SQLiteDatabase db) {
199        LogUtil.w(LogUtil.BUGLE_TAG, "Rebuilt databases: reseting related state");
200        // Clear other things that implicitly reference the DB
201        SyncManager.resetLastSyncTimestamps();
202    }
203
204    @Override
205    public void onActivityResume() {
206        // Perform an incremental sync and register for changes if necessary
207        mSyncManager.updateSyncObserver(mContext);
208
209        // Trigger a participant refresh if needed, we should only need to refresh if there is
210        // contact change while the activity was paused.
211        ParticipantRefresh.refreshParticipantsIfNeeded();
212    }
213
214    @Override
215    public void onApplicationCreated() {
216        FixupMessageStatusOnStartupAction.fixupMessageStatus();
217        ProcessPendingMessagesAction.processFirstPendingMessage();
218        SyncManager.immediateSync();
219
220        if (OsUtil.isAtLeastL_MR1()) {
221            // Start listening for subscription change events for refreshing self participants.
222            PhoneUtils.getDefault().toLMr1().registerOnSubscriptionsChangedListener(
223                    new SubscriptionManager.OnSubscriptionsChangedListener() {
224                        @Override
225                        public void onSubscriptionsChanged() {
226                            // TODO: This dynamically changes the mms config that app is
227                            // currently using. It may cause inconsistency in some cases. We need
228                            // to check the usage of mms config and handle the dynamic change
229                            // gracefully
230                            MmsConfig.loadAsync();
231                            ParticipantRefresh.refreshSelfParticipants();
232                        }
233                    });
234        }
235    }
236}
237