From 569da9ff5a34d900e34eb4c669e88907c9c9f8da Mon Sep 17 00:00:00 2001 From: Dongwon Kang Date: Mon, 6 Nov 2017 09:53:52 -0800 Subject: [PATCH] Add MediaUpdateService in SystemServer Test: play mp4 file and install & uninstall media update apk. Bug: 67908547 Change-Id: I17f91a85994da9a43e08734f7e79311bee62eab1 --- services/core/Android.bp | 1 + .../server/media/MediaUpdateService.java | 146 ++++++++++++++++++ .../java/com/android/server/SystemServer.java | 5 + 3 files changed, 152 insertions(+) create mode 100644 services/core/java/com/android/server/media/MediaUpdateService.java diff --git a/services/core/Android.bp b/services/core/Android.bp index 9fb26819dae07..3369458595a87 100644 --- a/services/core/Android.bp +++ b/services/core/Android.bp @@ -16,6 +16,7 @@ java_library_static { ":installd_aidl", ":storaged_aidl", ":vold_aidl", + ":mediaupdateservice_aidl", "java/com/android/server/EventLogTags.logtags", "java/com/android/server/am/EventLogTags.logtags", ], diff --git a/services/core/java/com/android/server/media/MediaUpdateService.java b/services/core/java/com/android/server/media/MediaUpdateService.java new file mode 100644 index 0000000000000..3c9d24ac0087f --- /dev/null +++ b/services/core/java/com/android/server/media/MediaUpdateService.java @@ -0,0 +1,146 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.media; + +import android.content.Context; +import android.content.Intent; +import android.media.IMediaResourceMonitor; +import android.os.Binder; +import android.os.UserHandle; +import android.os.UserManager; +import android.util.Log; +import android.util.Slog; +import com.android.server.SystemService; + +import android.content.BroadcastReceiver; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.os.IBinder; +import android.os.PatternMatcher; +import android.os.ServiceManager; +import android.media.IMediaExtractorUpdateService; + +import java.lang.Exception; + +/** This class provides a system service that manages media framework updates. */ +public class MediaUpdateService extends SystemService { + private static final String TAG = "MediaUpdateService"; + private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); + private static final String MEDIA_UPDATE_PACKAGE_NAME = "com.android.media.update"; + private static final String EXTRACTOR_UPDATE_SERVICE_NAME = "media.extractor.update"; + + private IMediaExtractorUpdateService mMediaExtractorUpdateService; + + public MediaUpdateService(Context context) { + super(context); + } + + @Override + public void onStart() { + connect(); + registerBroadcastReceiver(); + } + + private void connect() { + IBinder binder = ServiceManager.getService(EXTRACTOR_UPDATE_SERVICE_NAME); + if (binder != null) { + try { + binder.linkToDeath(new IBinder.DeathRecipient() { + @Override + public void binderDied() { + Slog.w(TAG, "mediaextractor died; reconnecting"); + mMediaExtractorUpdateService = null; + connect(); + } + }, 0); + } catch (Exception e) { + binder = null; + } + } + if (binder != null) { + mMediaExtractorUpdateService = IMediaExtractorUpdateService.Stub.asInterface(binder); + packageStateChanged(); + } else { + Slog.w(TAG, EXTRACTOR_UPDATE_SERVICE_NAME + " not found."); + } + } + + private void registerBroadcastReceiver() { + BroadcastReceiver updateReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_SYSTEM) + != UserHandle.USER_SYSTEM) { + // Ignore broadcast for non system users. We don't want to update system + // service multiple times. + return; + } + switch (intent.getAction()) { + case Intent.ACTION_PACKAGE_REMOVED: + if (intent.getExtras().getBoolean(Intent.EXTRA_REPLACING)) { + // The existing package is updated. Will be handled with the + // following ACTION_PACKAGE_ADDED case. + return; + } + packageStateChanged(); + break; + case Intent.ACTION_PACKAGE_CHANGED: + packageStateChanged(); + break; + case Intent.ACTION_PACKAGE_ADDED: + packageStateChanged(); + break; + } + } + }; + IntentFilter filter = new IntentFilter(); + filter.addAction(Intent.ACTION_PACKAGE_ADDED); + filter.addAction(Intent.ACTION_PACKAGE_REMOVED); + filter.addAction(Intent.ACTION_PACKAGE_CHANGED); + filter.addDataScheme("package"); + filter.addDataSchemeSpecificPart(MEDIA_UPDATE_PACKAGE_NAME, PatternMatcher.PATTERN_LITERAL); + + getContext().registerReceiverAsUser(updateReceiver, UserHandle.ALL, filter, + null /* broadcast permission */, null /* handler */); + } + + private void packageStateChanged() { + ApplicationInfo packageInfo = null; + boolean pluginsAvailable = false; + try { + packageInfo = getContext().getPackageManager().getApplicationInfo( + MEDIA_UPDATE_PACKAGE_NAME, PackageManager.MATCH_SYSTEM_ONLY); + pluginsAvailable = packageInfo.enabled; + } catch (Exception e) { + Slog.v(TAG, "package '" + MEDIA_UPDATE_PACKAGE_NAME + "' not installed"); + } + loadExtractorPlugins( + (packageInfo != null && pluginsAvailable) ? packageInfo.sourceDir : ""); + } + + private void loadExtractorPlugins(String apkPath) { + try { + if (mMediaExtractorUpdateService != null) { + mMediaExtractorUpdateService.loadPlugins(apkPath); + } + } catch (Exception e) { + Slog.w(TAG, "Error in loadPlugins", e); + } + } +} diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 4310a98d80001..3199bfa494559 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -80,6 +80,7 @@ import com.android.server.job.JobSchedulerService; import com.android.server.lights.LightsService; import com.android.server.media.MediaResourceMonitorService; import com.android.server.media.MediaRouterService; +import com.android.server.media.MediaUpdateService; import com.android.server.media.MediaSessionService; import com.android.server.media.projection.MediaProjectionManagerService; import com.android.server.net.NetworkPolicyManagerService; @@ -1442,6 +1443,10 @@ public final class SystemServer { mSystemServiceManager.startService(MediaSessionService.class); traceEnd(); + traceBeginAndSlog("StartMediaUpdateService"); + mSystemServiceManager.startService(MediaUpdateService.class); + traceEnd(); + if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_HDMI_CEC)) { traceBeginAndSlog("StartHdmiControlService"); mSystemServiceManager.startService(HdmiControlService.class);