1dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim/*
2dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim * Copyright 2018 The Android Open Source Project
3dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim *
4dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim * Licensed under the Apache License, Version 2.0 (the "License");
5dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim * you may not use this file except in compliance with the License.
6dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim * You may obtain a copy of the License at
7dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim *
8dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim *      http://www.apache.org/licenses/LICENSE-2.0
9dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim *
10dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim * Unless required by applicable law or agreed to in writing, software
11dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim * distributed under the License is distributed on an "AS IS" BASIS,
12dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim * See the License for the specific language governing permissions and
14dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim * limitations under the License.
15dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim */
16dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim
17dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kimpackage com.android.media;
18dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim
19dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kimimport static android.media.SessionToken2.TYPE_SESSION;
20dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kimimport static android.media.SessionToken2.TYPE_SESSION_SERVICE;
21dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kimimport static android.media.SessionToken2.TYPE_LIBRARY_SERVICE;
22dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim
23dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kimimport android.content.Context;
24dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kimimport android.content.Intent;
25dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kimimport android.content.pm.PackageManager;
26dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kimimport android.content.pm.PackageManager.NameNotFoundException;
27dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kimimport android.content.pm.ResolveInfo;
28dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kimimport android.media.MediaLibraryService2;
29dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kimimport android.media.MediaSessionService2;
30dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kimimport android.media.SessionToken2;
31dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kimimport android.media.SessionToken2.TokenType;
32dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kimimport android.media.update.SessionToken2Provider;
33dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kimimport android.os.Bundle;
34dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kimimport android.os.IBinder;
35dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kimimport android.text.TextUtils;
36dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim
379ddc2096deaae0fa940d1d80d0f415ddb1ba32b8Jaewan Kimimport java.util.List;
389ddc2096deaae0fa940d1d80d0f415ddb1ba32b8Jaewan Kim
39dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kimpublic class SessionToken2Impl implements SessionToken2Provider {
40dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim    private static final String KEY_UID = "android.media.token.uid";
41dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim    private static final String KEY_TYPE = "android.media.token.type";
42dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim    private static final String KEY_PACKAGE_NAME = "android.media.token.package_name";
43dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim    private static final String KEY_SERVICE_NAME = "android.media.token.service_name";
44dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim    private static final String KEY_ID = "android.media.token.id";
45dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim    private static final String KEY_SESSION_BINDER = "android.media.token.session_binder";
46dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim
47dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim    private final SessionToken2 mInstance;
48dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim    private final int mUid;
49dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim    private final @TokenType int mType;
50dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim    private final String mPackageName;
51dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim    private final String mServiceName;
52dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim    private final String mId;
53dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim    private final IMediaSession2 mSessionBinder;
54dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim
555830d047eda8c4b9401214b590efbf1b9e8a1622Jaewan Kim    /**
5681c1b87234bdab435259acd355ba2df4730da3ceJaewan Kim     * Public constructor for the legacy support (i.e. browser can try connecting to any browser
5781c1b87234bdab435259acd355ba2df4730da3ceJaewan Kim     * service if it knows the service name)
585830d047eda8c4b9401214b590efbf1b9e8a1622Jaewan Kim     */
595830d047eda8c4b9401214b590efbf1b9e8a1622Jaewan Kim    public SessionToken2Impl(Context context, SessionToken2 instance,
605830d047eda8c4b9401214b590efbf1b9e8a1622Jaewan Kim            String packageName, String serviceName, int uid) {
615830d047eda8c4b9401214b590efbf1b9e8a1622Jaewan Kim        if (TextUtils.isEmpty(packageName)) {
6205625413ac93a2fcec0e96781745c0815ec59fb9Hyundo Moon            throw new IllegalArgumentException("packageName shouldn't be empty");
635830d047eda8c4b9401214b590efbf1b9e8a1622Jaewan Kim        }
645830d047eda8c4b9401214b590efbf1b9e8a1622Jaewan Kim        if (TextUtils.isEmpty(serviceName)) {
6505625413ac93a2fcec0e96781745c0815ec59fb9Hyundo Moon            throw new IllegalArgumentException("serviceName shouldn't be empty");
665830d047eda8c4b9401214b590efbf1b9e8a1622Jaewan Kim        }
67dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim        mInstance = instance;
685830d047eda8c4b9401214b590efbf1b9e8a1622Jaewan Kim        // Calculate uid if it's not specified.
695830d047eda8c4b9401214b590efbf1b9e8a1622Jaewan Kim        final PackageManager manager = context.getPackageManager();
70dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim        if (uid < 0) {
71dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim            try {
72dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim                uid = manager.getPackageUid(packageName, 0);
73dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim            } catch (NameNotFoundException e) {
745830d047eda8c4b9401214b590efbf1b9e8a1622Jaewan Kim                throw new IllegalArgumentException("Cannot find package " + packageName);
75dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim            }
76dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim        }
77dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim        mUid = uid;
789ddc2096deaae0fa940d1d80d0f415ddb1ba32b8Jaewan Kim
799ddc2096deaae0fa940d1d80d0f415ddb1ba32b8Jaewan Kim        // Infer id and type from package name and service name
809ddc2096deaae0fa940d1d80d0f415ddb1ba32b8Jaewan Kim        // TODO(jaewan): Handle multi-user.
819ddc2096deaae0fa940d1d80d0f415ddb1ba32b8Jaewan Kim        String id = getSessionIdFromService(manager, MediaLibraryService2.SERVICE_INTERFACE,
829ddc2096deaae0fa940d1d80d0f415ddb1ba32b8Jaewan Kim                packageName, serviceName);
839ddc2096deaae0fa940d1d80d0f415ddb1ba32b8Jaewan Kim        if (id != null) {
849ddc2096deaae0fa940d1d80d0f415ddb1ba32b8Jaewan Kim            mId = id;
859ddc2096deaae0fa940d1d80d0f415ddb1ba32b8Jaewan Kim            mType = TYPE_LIBRARY_SERVICE;
869ddc2096deaae0fa940d1d80d0f415ddb1ba32b8Jaewan Kim        } else {
875830d047eda8c4b9401214b590efbf1b9e8a1622Jaewan Kim            // retry with session service
889ddc2096deaae0fa940d1d80d0f415ddb1ba32b8Jaewan Kim            mId = getSessionIdFromService(manager, MediaSessionService2.SERVICE_INTERFACE,
899ddc2096deaae0fa940d1d80d0f415ddb1ba32b8Jaewan Kim                    packageName, serviceName);
909ddc2096deaae0fa940d1d80d0f415ddb1ba32b8Jaewan Kim            mType = TYPE_SESSION_SERVICE;
91dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim        }
929ddc2096deaae0fa940d1d80d0f415ddb1ba32b8Jaewan Kim        if (mId == null) {
935830d047eda8c4b9401214b590efbf1b9e8a1622Jaewan Kim            throw new IllegalArgumentException("service " + serviceName + " doesn't implement"
949ddc2096deaae0fa940d1d80d0f415ddb1ba32b8Jaewan Kim                    + " session service nor library service. Use service's full name.");
955830d047eda8c4b9401214b590efbf1b9e8a1622Jaewan Kim        }
965830d047eda8c4b9401214b590efbf1b9e8a1622Jaewan Kim        mPackageName = packageName;
975830d047eda8c4b9401214b590efbf1b9e8a1622Jaewan Kim        mServiceName = serviceName;
985830d047eda8c4b9401214b590efbf1b9e8a1622Jaewan Kim        mSessionBinder = null;
995830d047eda8c4b9401214b590efbf1b9e8a1622Jaewan Kim    }
1005830d047eda8c4b9401214b590efbf1b9e8a1622Jaewan Kim
1010de7babb75683eba98af2db52101d262372235daChristofer Ã…kersten    SessionToken2Impl(int uid, int type, String packageName, String serviceName, String id,
1020de7babb75683eba98af2db52101d262372235daChristofer Ã…kersten            IMediaSession2 sessionBinder) {
103adab3c90df0b7c55cee87df4613aafc250be0d88Jaewan Kim        // TODO(jaewan): Add sanity check (b/73863865)
1045830d047eda8c4b9401214b590efbf1b9e8a1622Jaewan Kim        mUid = uid;
1055830d047eda8c4b9401214b590efbf1b9e8a1622Jaewan Kim        mType = type;
1065830d047eda8c4b9401214b590efbf1b9e8a1622Jaewan Kim        mPackageName = packageName;
1075830d047eda8c4b9401214b590efbf1b9e8a1622Jaewan Kim        mServiceName = serviceName;
108dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim        mId = id;
109dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim        mSessionBinder = sessionBinder;
1105830d047eda8c4b9401214b590efbf1b9e8a1622Jaewan Kim        mInstance = new SessionToken2(this);
111dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim    }
112dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim
1139ddc2096deaae0fa940d1d80d0f415ddb1ba32b8Jaewan Kim    private static String getSessionIdFromService(PackageManager manager, String serviceInterface,
1149ddc2096deaae0fa940d1d80d0f415ddb1ba32b8Jaewan Kim            String packageName, String serviceName) {
1159ddc2096deaae0fa940d1d80d0f415ddb1ba32b8Jaewan Kim        Intent serviceIntent = new Intent(serviceInterface);
1169ddc2096deaae0fa940d1d80d0f415ddb1ba32b8Jaewan Kim        serviceIntent.setPackage(packageName);
1179ddc2096deaae0fa940d1d80d0f415ddb1ba32b8Jaewan Kim        // Use queryIntentServices to find services with MediaLibraryService2.SERVICE_INTERFACE.
1189ddc2096deaae0fa940d1d80d0f415ddb1ba32b8Jaewan Kim        // We cannot use resolveService with intent specified class name, because resolveService
1199ddc2096deaae0fa940d1d80d0f415ddb1ba32b8Jaewan Kim        // ignores actions if Intent.setClassName() is specified.
1209ddc2096deaae0fa940d1d80d0f415ddb1ba32b8Jaewan Kim        List<ResolveInfo> list = manager.queryIntentServices(
1219ddc2096deaae0fa940d1d80d0f415ddb1ba32b8Jaewan Kim                serviceIntent, PackageManager.GET_META_DATA);
1229ddc2096deaae0fa940d1d80d0f415ddb1ba32b8Jaewan Kim        if (list != null) {
1239ddc2096deaae0fa940d1d80d0f415ddb1ba32b8Jaewan Kim            for (int i = 0; i < list.size(); i++) {
1249ddc2096deaae0fa940d1d80d0f415ddb1ba32b8Jaewan Kim                ResolveInfo resolveInfo = list.get(i);
1259ddc2096deaae0fa940d1d80d0f415ddb1ba32b8Jaewan Kim                if (resolveInfo == null || resolveInfo.serviceInfo == null) {
1269ddc2096deaae0fa940d1d80d0f415ddb1ba32b8Jaewan Kim                    continue;
1279ddc2096deaae0fa940d1d80d0f415ddb1ba32b8Jaewan Kim                }
1289ddc2096deaae0fa940d1d80d0f415ddb1ba32b8Jaewan Kim                if (TextUtils.equals(resolveInfo.serviceInfo.name, serviceName)) {
1299ddc2096deaae0fa940d1d80d0f415ddb1ba32b8Jaewan Kim                    return getSessionId(resolveInfo);
1309ddc2096deaae0fa940d1d80d0f415ddb1ba32b8Jaewan Kim                }
1319ddc2096deaae0fa940d1d80d0f415ddb1ba32b8Jaewan Kim            }
1329ddc2096deaae0fa940d1d80d0f415ddb1ba32b8Jaewan Kim        }
1339ddc2096deaae0fa940d1d80d0f415ddb1ba32b8Jaewan Kim        return null;
1349ddc2096deaae0fa940d1d80d0f415ddb1ba32b8Jaewan Kim    }
1359ddc2096deaae0fa940d1d80d0f415ddb1ba32b8Jaewan Kim
136dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim    public static String getSessionId(ResolveInfo resolveInfo) {
137dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim        if (resolveInfo == null || resolveInfo.serviceInfo == null) {
138dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim            return null;
139dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim        } else if (resolveInfo.serviceInfo.metaData == null) {
140dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim            return "";
141dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim        } else {
142dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim            return resolveInfo.serviceInfo.metaData.getString(
143dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim                    MediaSessionService2.SERVICE_META_DATA, "");
144dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim        }
145dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim    }
146dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim
1475830d047eda8c4b9401214b590efbf1b9e8a1622Jaewan Kim    public SessionToken2 getInstance() {
1485830d047eda8c4b9401214b590efbf1b9e8a1622Jaewan Kim        return mInstance;
1495830d047eda8c4b9401214b590efbf1b9e8a1622Jaewan Kim    }
1505830d047eda8c4b9401214b590efbf1b9e8a1622Jaewan Kim
151dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim    @Override
152dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim    public String getPackageName_impl() {
153dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim        return mPackageName;
154dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim    }
155dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim
156dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim    @Override
157dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim    public int getUid_impl() {
158dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim        return mUid;
159dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim    }
160dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim
161dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim    @Override
162dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim    public String getId_imp() {
163dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim        return mId;
164dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim    }
165dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim
166dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim    @Override
167dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim    public int getType_impl() {
168dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim        return mType;
169dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim    }
170dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim
1710de7babb75683eba98af2db52101d262372235daChristofer Ã…kersten    String getServiceName() {
172dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim        return mServiceName;
173dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim    }
174dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim
1750de7babb75683eba98af2db52101d262372235daChristofer Ã…kersten    IMediaSession2 getSessionBinder() {
176dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim        return mSessionBinder;
177dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim    }
178dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim
1790de7babb75683eba98af2db52101d262372235daChristofer Ã…kersten    public static SessionToken2 fromBundle_impl(Bundle bundle) {
180dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim        if (bundle == null) {
181dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim            return null;
182dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim        }
183dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim        final int uid = bundle.getInt(KEY_UID);
184dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim        final @TokenType int type = bundle.getInt(KEY_TYPE, -1);
185dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim        final String packageName = bundle.getString(KEY_PACKAGE_NAME);
186dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim        final String serviceName = bundle.getString(KEY_SERVICE_NAME);
187dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim        final String id = bundle.getString(KEY_ID);
188dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim        final IBinder sessionBinder = bundle.getBinder(KEY_SESSION_BINDER);
189dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim
190dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim        // Sanity check.
191dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim        switch (type) {
192dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim            case TYPE_SESSION:
193dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim                if (sessionBinder == null) {
194dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim                    throw new IllegalArgumentException("Unexpected sessionBinder for session,"
195dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim                            + " binder=" + sessionBinder);
196dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim                }
197dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim                break;
198dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim            case TYPE_SESSION_SERVICE:
199dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim            case TYPE_LIBRARY_SERVICE:
200dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim                if (TextUtils.isEmpty(serviceName)) {
201dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim                    throw new IllegalArgumentException("Session service needs service name");
202dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim                }
203dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim                break;
204dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim            default:
205dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim                throw new IllegalArgumentException("Invalid type");
206dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim        }
207dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim        if (TextUtils.isEmpty(packageName) || id == null) {
208dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim            throw new IllegalArgumentException("Package name nor ID cannot be null.");
209dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim        }
2100de7babb75683eba98af2db52101d262372235daChristofer Ã…kersten        return new SessionToken2Impl(uid, type, packageName, serviceName, id,
2115830d047eda8c4b9401214b590efbf1b9e8a1622Jaewan Kim                sessionBinder != null ? IMediaSession2.Stub.asInterface(sessionBinder) : null)
2125830d047eda8c4b9401214b590efbf1b9e8a1622Jaewan Kim                .getInstance();
213dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim    }
214dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim
215dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim    @Override
216dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim    public Bundle toBundle_impl() {
217dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim        Bundle bundle = new Bundle();
218dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim        bundle.putInt(KEY_UID, mUid);
219dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim        bundle.putString(KEY_PACKAGE_NAME, mPackageName);
220dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim        bundle.putString(KEY_SERVICE_NAME, mServiceName);
221dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim        bundle.putString(KEY_ID, mId);
222dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim        bundle.putInt(KEY_TYPE, mType);
223dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim        bundle.putBinder(KEY_SESSION_BINDER,
224dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim                mSessionBinder != null ? mSessionBinder.asBinder() : null);
225dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim        return bundle;
226dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim    }
227dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim
228dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim    @Override
229dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim    public int hashCode_impl() {
230dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim        final int prime = 31;
231dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim        return mType
232dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim                + prime * (mUid
233dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim                + prime * (mPackageName.hashCode()
234dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim                + prime * (mId.hashCode()
235e38637402cf0426808f77b47483b83096112be5fSungsoo Lim                + prime * (mServiceName != null ? mServiceName.hashCode() : 0))));
236dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim    }
237dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim
238dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim    @Override
239dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim    public boolean equals_impl(Object obj) {
240dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim        if (!(obj instanceof SessionToken2)) {
241dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim            return false;
242dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim        }
243dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim        SessionToken2Impl other = from((SessionToken2) obj);
244e38637402cf0426808f77b47483b83096112be5fSungsoo Lim        return mUid == other.mUid
245e38637402cf0426808f77b47483b83096112be5fSungsoo Lim                && TextUtils.equals(mPackageName, other.mPackageName)
246e38637402cf0426808f77b47483b83096112be5fSungsoo Lim                && TextUtils.equals(mServiceName, other.mServiceName)
247e38637402cf0426808f77b47483b83096112be5fSungsoo Lim                && TextUtils.equals(mId, other.mId)
248e38637402cf0426808f77b47483b83096112be5fSungsoo Lim                && mType == other.mType;
249dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim    }
250dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim
251dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim    @Override
252dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim    public String toString_impl() {
253dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim        return "SessionToken {pkg=" + mPackageName + " id=" + mId + " type=" + mType
254dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim                + " service=" + mServiceName + " binder=" + mSessionBinder + "}";
255dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim    }
256dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim
2570de7babb75683eba98af2db52101d262372235daChristofer Ã…kersten    static SessionToken2Impl from(SessionToken2 token) {
258dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim        return ((SessionToken2Impl) token.getProvider());
259dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim    }
260dd4397861fd98aefae95e6d6036a96f499eaf8b1Jaewan Kim}
261