MmsFileProvider.java revision eb7b90f5b93db1230a5b64caa3d8d05a642e33a6
1/*
2* Copyright (C) 2014 Samsung System LSI
3* Licensed under the Apache License, Version 2.0 (the "License");
4* you may not use this file except in compliance with the License.
5* You may obtain a copy of the License at
6*
7*      http://www.apache.org/licenses/LICENSE-2.0
8*
9* Unless required by applicable law or agreed to in writing, software
10* distributed under the License is distributed on an "AS IS" BASIS,
11* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12* See the License for the specific language governing permissions and
13* limitations under the License.
14*/
15package com.android.bluetooth.map;
16
17import android.annotation.TargetApi;
18import android.content.ContentProvider;
19import android.content.ContentValues;
20import android.database.Cursor;
21import android.net.Uri;
22import android.os.Bundle;
23import android.os.ParcelFileDescriptor;
24import android.provider.Telephony.Mms;
25import android.util.Log;
26
27import com.google.android.mms.MmsException;
28import com.google.android.mms.pdu.GenericPdu;
29import com.google.android.mms.pdu.PduComposer;
30import com.google.android.mms.pdu.PduPersister;
31
32import java.io.FileNotFoundException;
33import java.io.FileOutputStream;
34import java.io.IOException;
35
36/**
37 * Provider to let the MMS subsystem read data from it own database from another process.
38 * Workaround for missing access to sendStoredMessage().
39 */
40@TargetApi(19)
41public class MmsFileProvider extends ContentProvider {
42    static final String TAG = "BluetoothMmsFileProvider";
43    private PipeWriter mPipeWriter = new PipeWriter();
44
45    /*package*/
46    static final Uri CONTENT_URI = Uri.parse("content://com.android.bluetooth.map.MmsFileProvider");
47
48    @Override
49    public boolean onCreate() {
50        return true;
51    }
52
53    @Override
54    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
55            String sortOrder) {
56        // Don't support queries.
57        return null;
58    }
59
60    @Override
61    public Uri insert(Uri uri, ContentValues values) {
62        // Don't support inserts.
63        return null;
64    }
65
66    @Override
67    public int delete(Uri uri, String selection, String[] selectionArgs) {
68        // Don't support deletes.
69        return 0;
70    }
71
72    @Override
73    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
74        // Don't support updates.
75        return 0;
76    }
77
78    @Override
79    public String getType(Uri uri) {
80        // For this sample, assume all files have no type.
81        return null;
82    }
83
84    @Override
85    public ParcelFileDescriptor openFile(Uri uri, String fileMode) throws FileNotFoundException {
86        String idStr = uri.getLastPathSegment();
87        if(idStr == null) {
88            throw new FileNotFoundException("Unable to extract message handle from: " + uri);
89        }
90        try {
91            long id = Long.parseLong(idStr);
92        } catch (NumberFormatException e) {
93            Log.w(TAG,e);
94            throw new FileNotFoundException("Unable to extract message handle from: " + uri);
95        }
96        Uri messageUri = Mms.CONTENT_URI.buildUpon().appendEncodedPath(idStr).build();
97
98        return openPipeHelper (messageUri, null, null, null, mPipeWriter);
99    }
100
101
102    public class PipeWriter implements PipeDataWriter<Cursor> {
103        /**
104         * Generate a message based on the cursor, and write the encoded data to the stream.
105         */
106
107        public void writeDataToPipe(ParcelFileDescriptor output, Uri uri, String mimeType,
108                Bundle opts, Cursor c) {
109            if (BluetoothMapService.DEBUG) Log.d(TAG, "writeDataToPipe(): uri=" + uri.toString() +
110                    " - getLastPathSegment() = " + uri.getLastPathSegment());
111
112            FileOutputStream fout = null;
113            GenericPdu pdu = null;
114            PduPersister pduPersister = null;
115
116            try {
117                fout = new FileOutputStream(output.getFileDescriptor());
118                pduPersister = PduPersister.getPduPersister(getContext());
119                pdu = pduPersister.load(uri);
120                byte[] bytes = (new PduComposer(getContext(), pdu)).make();
121                fout.write(bytes);
122
123            } catch (IOException e) {
124                Log.w(TAG, e);
125                /* TODO: How to signal the error to the calling entity? Had expected writeDataToPipe
126                 *       to throw IOException?
127                 */
128            } catch (MmsException e) {
129                Log.w(TAG, e);
130                /* TODO: How to signal the error to the calling entity? Had expected writeDataToPipe
131                 *       to throw IOException?
132                 */
133            } finally {
134                if(pduPersister != null) pduPersister.release();
135                try {
136                    fout.flush();
137                } catch (IOException e) {
138                    Log.w(TAG, "IOException: ", e);
139                }
140                try {
141                    fout.close();
142                } catch (IOException e) {
143                    Log.w(TAG, "IOException: ", e);
144                }
145            }
146        }
147    }
148
149
150}
151