美文网首页
Android Framework media provide

Android Framework media provide

作者: Nothing_655f | 来源:发表于2020-11-24 15:31 被阅读0次

Android Framework media providers 随笔

遇到一个问题是多媒体扫描失败:

11-24 09:50:54.424  3886  3886 E lowmemorykiller: Error writing /proc/4647/oom_score_adj; errno=22
11-24 09:50:54.430  4216  4227 E JavaBinder: !!! FAILED BINDER TRANSACTION !!!  (parcel size = 76)
11-24 09:50:54.431  4216  4227 I ActivityManager: Process android.process.media (pid 4647) has died

从logcat 中可以看到的时候 这个服务com.android.providers.media/.MediaScannerService 启动超时了

Line 2012: 11-23 11:55:04.410  4216  4229 I ActivityManager: Force stopping com.android.providers.media appid=10006 user=-1: vold reset
Line 2309: 11-24 09:47:58.651  4216  4394 I BroadcastQueue: Delay finish: com.android.providers.media/.MediaScannerReceiver
Line 2338: 11-24 09:48:13.653  4216  4229 I ActivityManager: Waited long enough for: ServiceRecord{50712f4 u0 com.android.providers.media/.MediaScannerService}
Line 2450: 11-24 09:50:54.023  4647  4647 I chatty  : uid=10006(com.android.providers.media) expire 1 line
Line 2457: 11-24 09:50:54.029  4647  5471 I chatty  : uid=10006(com.android.providers.media) expire 13 lines
Line 2540: 11-24 09:50:54.431  4216  4227 I ActivityManager: Existing provider com.android.providers.media/.MediaProvider is crashing; detaching ProcessRecord{65cbd94 4694:com.xxx.xxx/1000}
Line 2543: 11-24 09:50:54.431  4216  4227 W ActivityManager: Scheduling restart of crashed service com.android.providers.media/.MediaScannerService in 351562ms

1、com.android.providers.media 和 com.android.providers.media/.MediaScannerService 到底是在哪里定义声明的?

2、Why com.android.providers.media/.MediaProvider is crashing?

带着问题扩展开来学习,遇到什么记录什么,慢慢搭建系统的体系

平台:Android 7.1

1、com.android.providers.media 与 MediaScannerService

看 frameworks\base\media\java\android\media\MediaScannerConnection.java 的构造方法和connect 方法, 其注释和接口实现可以回答之前的疑问

/**
 * MediaScannerConnection provides a way for applications to pass a
 * newly created or downloaded media file to the media scanner service.
 * The media scanner service will read metadata from the file and add
 * the file to the media content provider.
 * The MediaScannerConnectionClient provides an interface for the
 * media scanner service to return the Uri for a newly scanned file
 * to the client of the MediaScannerConnection class.
 */
public class MediaScannerConnection implements ServiceConnection

如下接口通过

​ new ComponentName("com.android.providers.media",
​ "com.android.providers.media.MediaScannerService"));

/**
* Initiates a connection to the media scanner service.
* {@link MediaScannerConnectionClient#onMediaScannerConnected()}
* will be called when the connection is established.
*/
public void connect() {
    synchronized (this) {
        if (!mConnected) {
            Intent intent = new Intent(IMediaScannerService.class.getName());
            intent.setComponent(
                    new ComponentName("com.android.providers.media",
                            "com.android.providers.media.MediaScannerService"));
            mContext.bindService(intent, this, Context.BIND_AUTO_CREATE);
            mConnected = true;
        }
    }
}

而 MediaScannerService 我们只需要看如下文件中的注释就对其流程有一个清晰的了解

frameworks\base\media\java\android\media\MediaScanner.java

/**
 * Internal service helper that no-one should use directly.
 *
 * The way the scan currently works is:
 * - The Java MediaScannerService creates a MediaScanner (this class), and calls
 *   MediaScanner.scanDirectories on it.
 * - scanDirectories() calls the native processDirectory() for each of the specified directories.
 * - the processDirectory() JNI method wraps the provided mediascanner client in a native
 *   'MyMediaScannerClient' class, then calls processDirectory() on the native MediaScanner
 *   object (which got created when the Java MediaScanner was created).
 * - native MediaScanner.processDirectory() calls
 *   doProcessDirectory(), which recurses over the folder, and calls
 *   native MyMediaScannerClient.scanFile() for every file whose extension matches.
 * - native MyMediaScannerClient.scanFile() calls back on Java MediaScannerClient.scanFile,
 *   which calls doScanFile, which after some setup calls back down to native code, calling
 *   MediaScanner.processFile().
 * - MediaScanner.processFile() calls one of several methods, depending on the type of the
 *   file: parseMP3, parseMP4, parseMidi, parseOgg or parseWMA.
 * - each of these methods gets metadata key/value pairs from the file, and repeatedly
 *   calls native MyMediaScannerClient.handleStringTag, which calls back up to its Java
 *   counterparts in this file.
 * - Java handleStringTag() gathers the key/value pairs that it's interested in.
 * - once processFile returns and we're back in Java code in doScanFile(), it calls
 *   Java MyMediaScannerClient.endFile(), which takes all the data that's been
 *   gathered and inserts an entry in to the database.
 *
 * In summary:
 * Java MediaScannerService calls
 * Java MediaScanner scanDirectories, which calls
 * Java MediaScanner processDirectory (native method), which calls
 * native MediaScanner processDirectory, which calls
 * native MyMediaScannerClient scanFile, which calls
 * Java MyMediaScannerClient scanFile, which calls
 * Java MediaScannerClient doScanFile, which calls
 * Java MediaScanner processFile (native method), which calls
 * native MediaScanner processFile, which calls
 * native parseMP3, parseMP4, parseMidi, parseOgg or parseWMA, which calls
 * native MyMediaScanner handleStringTag, which calls
 * Java MyMediaScanner handleStringTag.
 * Once MediaScanner processFile returns, an entry is inserted in to the database.
 *
 * The MediaScanner class is not thread-safe, so it should only be used in a single threaded manner.
 *
 * {@hide}
 */
public class MediaScanner implements AutoCloseable

2、Why com.android.providers.media/.MediaProvider is crashing?

frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java getContentProviderImpl函数中会对 OomAdj 优先级进行调整,如果调整失败和判断进程不可活, 则调用 appDiedLocked kill 其进程

    private ContentProviderHolder getContentProviderImpl(IApplicationThread caller,
            String name, IBinder token, boolean stable, int userId) {
            // ....
            boolean success = updateOomAdjLocked(cpr.proc);
            // XXX things have changed so updateOomAdjLocked doesn't actually tell us
            // if the process has been successfully adjusted.  So to reduce races with
            // it, we will check whether the process still exists.  Note that this doesn't
            // completely get rid of races with LMK killing the process, but should make
            // them much smaller.
            if (success && verifiedAdj != cpr.proc.setAdj && !isProcessAliveLocked(cpr.proc)) {
                success = false;
            }
            maybeUpdateProviderUsageStatsLocked(r, cpr.info.packageName, name);
            checkTime(startTime, "getContentProviderImpl: after updateOomAdj");
            if (DEBUG_PROVIDER) Slog.i(TAG_PROVIDER, "Adjust success: " + success);
            // NOTE: there is still a race here where a signal could be
            // pending on the process even though we managed to update its
            // adj level.  Not sure what to do about this, but at least
            // the race is now smaller.
            if (!success) {
                // Uh oh...  it looks like the provider's process
                // has been killed on us.  We need to wait for a new
                // process to be started, and make sure its death
                // doesn't kill our process.
                Slog.i(TAG, "Existing provider " + cpr.name.flattenToShortString()
                        + " is crashing; detaching " + r);
                boolean lastRef = decProviderCountLocked(conn, cpr, token, stable);
                checkTime(startTime, "getContentProviderImpl: before appDied");
                appDiedLocked(cpr.proc);
                checkTime(startTime, "getContentProviderImpl: after appDied");
                if (!lastRef) {
                    // This wasn't the last ref our process had on
                    // the provider...  we have now been killed, bail.
                    return null;
                }
                providerRunning = false;
                conn = null;
            } else {
                cpr.proc.verifiedAdj = cpr.proc.setAdj;
            }

其实最后之所以把文章标题写为随笔,就是还有未完成的事情要做。

虽然把 1 的疑问找到地方了,但是其实是引出来了更多疑问,什么时候调用,其他层逻辑实现

转一篇文章看看 Android开发——MediaProvider源码分析(1)

同样2 也是,OomAdj 为什么会调整失败,调整失败后怎么做 等等...

这些都是会引发新的思考,并且跟自身已有的知识点联系起来,所以系统知识技能需要不断思考,实践学习

相关文章

网友评论

      本文标题:Android Framework media provide

      本文链接:https://www.haomeiwen.com/subject/ikgiiktx.html