From 19ba61affbc0c4a4454abc6cf09f70ea428d1a62 Mon Sep 17 00:00:00 2001 From: Chulwoo Lee Date: Wed, 3 Sep 2014 00:59:35 +0900 Subject: [PATCH] Notify of the update of TvInputInfo The TvInputInfo is updated when 1. the package is reinstalled. 2. the media on which a newer version of TV inputs exists become available. 3. the media on which a newer version of TV inputs exists become unavailable. BUG: 17349383 Change-Id: I983058b13678bd8ecf7d766dc8bdac5fed7df4a0 --- .../media/tv/ITvInputManagerCallback.aidl | 1 + .../java/android/media/tv/TvInputManager.java | 30 +++++++ .../server/tv/TvInputManagerService.java | 90 ++++++++++++++++--- 3 files changed, 109 insertions(+), 12 deletions(-) diff --git a/media/java/android/media/tv/ITvInputManagerCallback.aidl b/media/java/android/media/tv/ITvInputManagerCallback.aidl index 50a7636c09920..67926807b156a 100644 --- a/media/java/android/media/tv/ITvInputManagerCallback.aidl +++ b/media/java/android/media/tv/ITvInputManagerCallback.aidl @@ -24,4 +24,5 @@ oneway interface ITvInputManagerCallback { void onInputStateChanged(in String inputId, int state); void onInputAdded(in String inputId); void onInputRemoved(in String inputId); + void onInputUpdated(in String inputId); } diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java index b7a230c6b041b..f809f547a579b 100644 --- a/media/java/android/media/tv/TvInputManager.java +++ b/media/java/android/media/tv/TvInputManager.java @@ -477,6 +477,18 @@ public final class TvInputManager { */ public void onInputRemoved(String inputId) { } + + /** + * This is called when a TV input is updated. The update of TV input happens when it is + * reinstalled or the media on which the newer version of TV input exists is + * available/unavailable. + * + * @param inputId The id of the TV input. + * @hide + */ + @SystemApi + public void onInputUpdated(String inputId) { + } } private static final class TvInputCallbackRecord { @@ -518,6 +530,15 @@ public final class TvInputManager { } }); } + + public void postInputUpdated(final String inputId) { + mHandler.post(new Runnable() { + @Override + public void run() { + mListener.onInputUpdated(inputId); + } + }); + } } /** @@ -707,6 +728,15 @@ public final class TvInputManager { } } } + + @Override + public void onInputUpdated(String inputId) { + synchronized (mLock) { + for (TvInputListenerRecord record : mTvInputListenerRecordsList) { + record.postInputUpdated(inputId); + } + } + } }; try { if (mService != null) { diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java index 3380f710988a9..adae84fdae655 100644 --- a/services/core/java/com/android/server/tv/TvInputManagerService.java +++ b/services/core/java/com/android/server/tv/TvInputManagerService.java @@ -85,6 +85,7 @@ import java.io.FileDescriptor; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -139,7 +140,7 @@ public final class TvInputManagerService extends SystemService { registerBroadcastReceivers(); } else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) { synchronized (mLock) { - buildTvInputListLocked(mCurrentUserId); + buildTvInputListLocked(mCurrentUserId, null); buildTvContentRatingSystemListLocked(mCurrentUserId); } } @@ -148,19 +149,64 @@ public final class TvInputManagerService extends SystemService { private void registerBroadcastReceivers() { PackageMonitor monitor = new PackageMonitor() { + private void buildTvInputList(String[] packages) { + synchronized (mLock) { + buildTvInputListLocked(getChangingUserId(), packages); + buildTvContentRatingSystemListLocked(getChangingUserId()); + } + } + + @Override + public void onPackageUpdateFinished(String packageName, int uid) { + if (DEBUG) Slog.d(TAG, "onPackageUpdateFinished(packageName=" + packageName + ")"); + // This callback is invoked when the TV input is reinstalled. + // In this case, isReplacing() always returns true. + buildTvInputList(new String[] { packageName }); + } + + @Override + public void onPackagesAvailable(String[] packages) { + if (DEBUG) { + Slog.d(TAG, "onPackagesAvailable(packages=" + Arrays.toString(packages) + ")"); + } + // This callback is invoked when the media on which some packages exist become + // available. + if (isReplacing()) { + buildTvInputList(packages); + } + } + + @Override + public void onPackagesUnavailable(String[] packages) { + // This callback is invoked when the media on which some packages exist become + // unavailable. + if (DEBUG) { + Slog.d(TAG, "onPackagesUnavailable(packages=" + Arrays.toString(packages) + + ")"); + } + if (isReplacing()) { + buildTvInputList(packages); + } + } + @Override public void onSomePackagesChanged() { + // TODO: Use finer-grained methods(e.g. onPackageAdded, onPackageRemoved) to manage + // the TV inputs. if (DEBUG) Slog.d(TAG, "onSomePackagesChanged()"); - synchronized (mLock) { - buildTvInputListLocked(mCurrentUserId); - buildTvContentRatingSystemListLocked(mCurrentUserId); + if (isReplacing()) { + if (DEBUG) Slog.d(TAG, "Skipped building TV input list due to replacing"); + // When the package is updated, buildTvInputListLocked is called in other + // methods instead. + return; } + buildTvInputList(null); } @Override public void onPackageRemoved(String packageName, int uid) { synchronized (mLock) { - UserState userState = getUserStateLocked(mCurrentUserId); + UserState userState = getUserStateLocked(getChangingUserId()); if (!userState.packageSet.contains(packageName)) { // Not a TV input package. return; @@ -218,13 +264,11 @@ public final class TvInputManagerService extends SystemService { component.getPackageName()) == PackageManager.PERMISSION_GRANTED; } - private void buildTvInputListLocked(int userId) { + private void buildTvInputListLocked(int userId, String[] updatedPackages) { UserState userState = getUserStateLocked(userId); userState.packageSet.clear(); - if (DEBUG) { - Slog.d(TAG, "buildTvInputList"); - } + if (DEBUG) Slog.d(TAG, "buildTvInputList"); PackageManager pm = mContext.getPackageManager(); List services = pm.queryIntentServices( new Intent(TvInputService.SERVICE_INTERFACE), @@ -278,6 +322,15 @@ public final class TvInputManagerService extends SystemService { for (String inputId : inputMap.keySet()) { if (!userState.inputMap.containsKey(inputId)) { notifyInputAddedLocked(userState, inputId); + } else if (updatedPackages != null) { + // Notify the package updates + TvInputState inputState = inputMap.get(inputId); + for (String updatedPackage : updatedPackages) { + if (inputState.info.getComponent().getPackageName().equals(updatedPackage)) { + notifyInputUpdatedLocked(userState, inputId); + break; + } + } } } @@ -337,7 +390,7 @@ public final class TvInputManagerService extends SystemService { userState = new UserState(mContext, userId); } mUserStates.put(userId, userState); - buildTvInputListLocked(userId); + buildTvInputListLocked(userId, null); buildTvContentRatingSystemListLocked(userId); } } @@ -649,6 +702,19 @@ public final class TvInputManagerService extends SystemService { } } + private void notifyInputUpdatedLocked(UserState userState, String inputId) { + if (DEBUG) { + Slog.d(TAG, "notifyInputUpdatedLocked(inputId=" + inputId + ")"); + } + for (ITvInputManagerCallback callback : userState.callbackSet) { + try { + callback.onInputUpdated(inputId); + } catch (RemoteException e) { + Slog.e(TAG, "failed to report updated input to callback", e); + } + } + } + private void notifyInputStateChangedLocked(UserState userState, String inputId, int state, ITvInputManagerCallback targetCallback) { if (DEBUG) { @@ -1813,7 +1879,7 @@ public final class TvInputManagerService extends SystemService { private void addTvInputLocked(TvInputInfo inputInfo) { ServiceState serviceState = getServiceStateLocked(mComponent, mUserId); serviceState.inputList.add(inputInfo); - buildTvInputListLocked(mUserId); + buildTvInputListLocked(mUserId, null); } @Override @@ -1851,7 +1917,7 @@ public final class TvInputManagerService extends SystemService { } } if (removed) { - buildTvInputListLocked(mUserId); + buildTvInputListLocked(mUserId, null); mTvInputHardwareManager.removeTvInput(inputId); } else { Slog.e(TAG, "failed to remove input " + inputId);