Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 19ba61af authored by Chulwoo Lee's avatar Chulwoo Lee
Browse files

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
parent 0c1964e7
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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);
}
+30 −0
Original line number Diff line number Diff line
@@ -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) {
+78 −12
Original line number Diff line number Diff line
@@ -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<ResolveInfo> 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);