blob: 3e9d789de861c45e1684326ac578a84a804bd49f [file] [log] [blame]
/*
* Copyright (C) 2019 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 android.appenumeration.cts.query;
import static android.appenumeration.cts.Constants.ACTION_GET_INSTALLED_PACKAGES;
import static android.appenumeration.cts.Constants.ACTION_GET_PACKAGE_INFO;
import static android.appenumeration.cts.Constants.ACTION_QUERY_ACTIVITIES;
import static android.appenumeration.cts.Constants.ACTION_QUERY_PROVIDERS;
import static android.appenumeration.cts.Constants.ACTION_QUERY_SERVICES;
import static android.appenumeration.cts.Constants.ACTION_SEND_RESULT;
import static android.appenumeration.cts.Constants.ACTION_START_DIRECTLY;
import static android.appenumeration.cts.Constants.ACTION_START_FOR_RESULT;
import static android.appenumeration.cts.Constants.ACTION_START_SENDER_FOR_RESULT;
import static android.appenumeration.cts.Constants.EXTRA_ERROR;
import static android.appenumeration.cts.Constants.EXTRA_FLAGS;
import static android.appenumeration.cts.Constants.EXTRA_REMOTE_CALLBACK;
import static android.content.Intent.EXTRA_RETURN_RESULT;
import android.app.Activity;
import android.app.PendingIntent;
import android.appenumeration.cts.Constants;
import android.appenumeration.cts.MissingBroadcastException;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentSender;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.PatternMatcher;
import android.os.RemoteCallback;
import android.util.SparseArray;
public class TestActivity extends Activity {
SparseArray<RemoteCallback> callbacks = new SparseArray<>();
private Handler mainHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
mainHandler = new Handler(getMainLooper());
super.onCreate(savedInstanceState);
handleIntent(getIntent());
}
private void handleIntent(Intent intent) {
RemoteCallback remoteCallback = intent.getParcelableExtra(EXTRA_REMOTE_CALLBACK);
try {
final String action = intent.getAction();
final Intent queryIntent = intent.getParcelableExtra(Intent.EXTRA_INTENT);
if (ACTION_GET_PACKAGE_INFO.equals(action)) {
final String packageName = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME);
sendPackageInfo(remoteCallback, packageName);
} else if (ACTION_START_FOR_RESULT.equals(action)) {
final String packageName = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME);
int requestCode = RESULT_FIRST_USER + callbacks.size();
callbacks.put(requestCode, remoteCallback);
startActivityForResult(
new Intent(ACTION_SEND_RESULT).setComponent(
new ComponentName(packageName, getClass().getCanonicalName())),
requestCode);
// don't send anything... await result callback
} else if (ACTION_SEND_RESULT.equals(action)) {
try {
setResult(RESULT_OK,
getIntent().putExtra(
Intent.EXTRA_RETURN_RESULT,
getPackageManager().getPackageInfo(getCallingPackage(), 0)));
} catch (PackageManager.NameNotFoundException e) {
setResult(RESULT_FIRST_USER, new Intent().putExtra("error", e));
}
finish();
} else if (ACTION_QUERY_ACTIVITIES.equals(action)) {
sendQueryIntentActivities(remoteCallback, queryIntent);
} else if (ACTION_QUERY_SERVICES.equals(action)) {
sendQueryIntentServices(remoteCallback, queryIntent);
} else if (ACTION_QUERY_PROVIDERS.equals(action)) {
sendQueryIntentProviders(remoteCallback, queryIntent);
} else if (ACTION_START_DIRECTLY.equals(action)) {
try {
startActivity(queryIntent);
remoteCallback.sendResult(new Bundle());
} catch (ActivityNotFoundException e) {
sendError(remoteCallback, e);
}
finish();
} else if (ACTION_GET_INSTALLED_PACKAGES.equals(action)) {
sendGetInstalledPackages(remoteCallback, queryIntent.getIntExtra(EXTRA_FLAGS, 0));
} else if (ACTION_START_SENDER_FOR_RESULT.equals(action)) {
PendingIntent pendingIntent = intent.getParcelableExtra("pendingIntent");
int requestCode = RESULT_FIRST_USER + callbacks.size();
callbacks.put(requestCode, remoteCallback);
try {
startIntentSenderForResult(pendingIntent.getIntentSender(), requestCode, null,
0, 0, 0);
} catch (IntentSender.SendIntentException e) {
sendError(remoteCallback, e);
}
} else if (Constants.ACTION_AWAIT_PACKAGE_REMOVED.equals(action)) {
final String packageName = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME);
awaitPackageBroadcast(
remoteCallback, packageName, Intent.ACTION_PACKAGE_REMOVED, 3000);
} else if (Constants.ACTION_AWAIT_PACKAGE_ADDED.equals(action)) {
final String packageName = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME);
awaitPackageBroadcast(
remoteCallback, packageName, Intent.ACTION_PACKAGE_ADDED, 3000);
} else {
sendError(remoteCallback, new Exception("unknown action " + action));
}
} catch (Exception e) {
sendError(remoteCallback, e);
}
}
private void awaitPackageBroadcast(RemoteCallback remoteCallback, String packageName,
String action, long timeoutMs) {
final IntentFilter filter = new IntentFilter(action);
filter.addDataScheme("package");
filter.addDataSchemeSpecificPart(packageName, PatternMatcher.PATTERN_LITERAL);
final Object token = new Object();
registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
final Bundle result = new Bundle();
result.putString(Constants.EXTRA_DATA, intent.getDataString());
remoteCallback.sendResult(result);
mainHandler.removeCallbacksAndMessages(token);
finish();
}
}, filter);
mainHandler.postDelayed(
() -> sendError(remoteCallback,
new MissingBroadcastException(action, timeoutMs)),
token, timeoutMs);
}
private void sendGetInstalledPackages(RemoteCallback remoteCallback, int flags) {
String[] packages =
getPackageManager().getInstalledPackages(flags)
.stream().map(p -> p.packageName).distinct().toArray(String[]::new);
Bundle result = new Bundle();
result.putStringArray(EXTRA_RETURN_RESULT, packages);
remoteCallback.sendResult(result);
finish();
}
private void sendQueryIntentActivities(RemoteCallback remoteCallback, Intent queryIntent) {
final String[] resolveInfos = getPackageManager().queryIntentActivities(
queryIntent, 0 /* flags */).stream()
.map(ri -> ri.activityInfo.applicationInfo.packageName)
.distinct()
.toArray(String[]::new);
Bundle result = new Bundle();
result.putStringArray(EXTRA_RETURN_RESULT, resolveInfos);
remoteCallback.sendResult(result);
finish();
}
private void sendQueryIntentServices(RemoteCallback remoteCallback, Intent queryIntent) {
final String[] resolveInfos = getPackageManager().queryIntentServices(
queryIntent, 0 /* flags */).stream()
.map(ri -> ri.serviceInfo.applicationInfo.packageName)
.distinct()
.toArray(String[]::new);
Bundle result = new Bundle();
result.putStringArray(EXTRA_RETURN_RESULT, resolveInfos);
remoteCallback.sendResult(result);
finish();
}
private void sendQueryIntentProviders(RemoteCallback remoteCallback, Intent queryIntent) {
final String[] resolveInfos = getPackageManager().queryIntentContentProviders(
queryIntent, 0 /* flags */).stream()
.map(ri -> ri.providerInfo.applicationInfo.packageName)
.distinct()
.toArray(String[]::new);
Bundle result = new Bundle();
result.putStringArray(EXTRA_RETURN_RESULT, resolveInfos);
remoteCallback.sendResult(result);
finish();
}
private void sendError(RemoteCallback remoteCallback, Exception failure) {
Bundle result = new Bundle();
result.putSerializable(EXTRA_ERROR, failure);
remoteCallback.sendResult(result);
finish();
}
private void sendPackageInfo(RemoteCallback remoteCallback, String packageName) {
final PackageInfo pi;
try {
pi = getPackageManager().getPackageInfo(packageName, 0);
} catch (PackageManager.NameNotFoundException e) {
sendError(remoteCallback, e);
return;
}
Bundle result = new Bundle();
result.putParcelable(EXTRA_RETURN_RESULT, pi);
remoteCallback.sendResult(result);
finish();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
final RemoteCallback remoteCallback = callbacks.get(requestCode);
if (resultCode != RESULT_OK) {
Exception e = (Exception) data.getSerializableExtra(EXTRA_ERROR);
sendError(remoteCallback, e == null ? new Exception("Result was " + resultCode) : e);
return;
}
final Bundle result = new Bundle();
result.putParcelable(EXTRA_RETURN_RESULT, data.getParcelableExtra(EXTRA_RETURN_RESULT));
remoteCallback.sendResult(result);
finish();
}
}