Merge changes I8953967a,If17eddad into oc-dev

* changes:
  Add go to web action for instant apps
  Fix when instant app notif is showing
This commit is contained in:
Jason Monk
2017-04-20 17:24:20 +00:00
committed by Android (Google) Code Review
4 changed files with 157 additions and 52 deletions

View File

@@ -1988,6 +1988,9 @@
<!-- Action label for launching app info on the specified app [CHAR LIMIT=20] -->
<string name="app_info">App info</string>
<!-- Action label for switching to web for an instant app [CHAR LIMIT=20] -->
<string name="go_to_web">Go to web</string>
<!-- Quick settings tile for toggling mobile data [CHAR LIMIT=20] -->
<string name="mobile_data">Mobile data</string>

View File

@@ -0,0 +1,69 @@
/*
* Copyright (C) 2017 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.systemui;
import android.os.RemoteException;
import android.util.Log;
import android.view.IDockedStackListener;
import android.view.WindowManagerGlobal;
import java.util.function.Consumer;
/**
* Utility wrapper to listen for whether or not a docked stack exists, to be
* used for things like the different overview icon in that mode.
*/
public class DockedStackExistsListener extends IDockedStackListener.Stub {
private static final String TAG = "DockedStackExistsListener";
private final Consumer<Boolean> mCallback;
private DockedStackExistsListener(Consumer<Boolean> callback) {
mCallback = callback;
}
@Override
public void onDividerVisibilityChanged(boolean visible) throws RemoteException {
}
@Override
public void onDockedStackExistsChanged(final boolean exists) throws RemoteException {
mCallback.accept(exists);
}
@Override
public void onDockedStackMinimizedChanged(boolean minimized, long animDuration,
boolean isHomeStackResizable) throws RemoteException {
}
@Override
public void onAdjustedForImeChanged(boolean adjustedForIme, long animDuration)
throws RemoteException {
}
@Override
public void onDockSideChanged(int newDockSide) throws RemoteException {
}
public static void register(Consumer<Boolean> callback) {
try {
WindowManagerGlobal.getWindowManagerService().registerDockedStackListener(
new DockedStackExistsListener(callback));
} catch (RemoteException e) {
Log.e(TAG, "Failed registering docked stack exists listener", e);
}
}
}

View File

@@ -47,6 +47,7 @@ import android.view.inputmethod.InputMethodManager;
import android.widget.FrameLayout;
import com.android.systemui.Dependency;
import com.android.systemui.DockedStackExistsListener;
import com.android.systemui.R;
import com.android.systemui.RecentsComponent;
import com.android.systemui.plugins.PluginListener;
@@ -566,40 +567,10 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
getImeSwitchButton().setOnClickListener(mImeSwitcherClickListener);
try {
WindowManagerGlobal.getWindowManagerService().registerDockedStackListener(new Stub() {
@Override
public void onDividerVisibilityChanged(boolean visible) throws RemoteException {
}
@Override
public void onDockedStackExistsChanged(final boolean exists) throws RemoteException {
mHandler.post(new Runnable() {
@Override
public void run() {
mDockedStackExists = exists;
updateRecentsIcon();
}
});
}
@Override
public void onDockedStackMinimizedChanged(boolean minimized, long animDuration,
boolean isHomeStackResizable) throws RemoteException {
}
@Override
public void onAdjustedForImeChanged(boolean adjustedForIme, long animDuration)
throws RemoteException {
}
@Override
public void onDockSideChanged(int newDockSide) throws RemoteException {
}
});
} catch (RemoteException e) {
Log.e(TAG, "Failed registering docked stack exists listener", e);
}
DockedStackExistsListener.register(exists -> mHandler.post(() -> {
mDockedStackExists = exists;
updateRecentsIcon();
}));
}
void updateRotatedViews() {

View File

@@ -28,6 +28,7 @@ import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.SynchronousUserSwitchObserver;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -50,11 +51,11 @@ import android.telecom.TelecomManager;
import android.util.ArraySet;
import android.util.Log;
import android.util.Pair;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.internal.telephony.IccCardConstants;
import com.android.internal.telephony.TelephonyIntents;
import com.android.systemui.Dependency;
import com.android.systemui.DockedStackExistsListener;
import com.android.systemui.R;
import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.qs.tiles.DndTile;
@@ -82,6 +83,8 @@ import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.util.NotificationChannels;
import java.util.List;
/**
* This class contains all of the policy about which icons are installed in the status
* bar at boot time. It goes through the normal API for icons, even though it probably
@@ -94,6 +97,7 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks,
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
public static final int LOCATION_STATUS_ICON_ID = R.drawable.stat_sys_location;
public static final int NUM_TASKS_FOR_INSTANT_APP_INFO = 5;
private final String mSlotCast;
private final String mSlotHotspot;
@@ -132,6 +136,7 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks,
private boolean mZenVisible;
private boolean mVolumeVisible;
private boolean mCurrentUserSetup;
private boolean mDockedStackExists;
private boolean mManagedProfileIconVisible = false;
private boolean mManagedProfileInQuietMode = false;
@@ -248,6 +253,10 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks,
noMan.cancel(notification.getTag(), notification.getId());
}
}
DockedStackExistsListener.register(exists -> {
mDockedStackExists = exists;
updateForegroundInstantApps();
});
}
public void destroy() {
@@ -495,23 +504,18 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks,
IPackageManager pm = AppGlobals.getPackageManager();
mCurrentNotifs.clear();
try {
ArraySet<Integer> stacksToCheck = new ArraySet<>();
int[] STACKS_TO_CHECK = new int[]{
StackId.FULLSCREEN_WORKSPACE_STACK_ID,
StackId.DOCKED_STACK_ID,
};
for (int i = 0; i < STACKS_TO_CHECK.length; i++) {
StackInfo info = ActivityManager.getService().getStackInfo(STACKS_TO_CHECK[i]);
if (info == null || info.topActivity == null) continue;
String pkg = info.topActivity.getPackageName();
if (!hasNotif(notifs, pkg, info.userId)) {
// TODO: Optimize by not always needing to get application info.
// Maybe cache non-ephemeral packages?
ApplicationInfo appInfo = pm.getApplicationInfo(pkg,
PackageManager.MATCH_UNINSTALLED_PACKAGES, info.userId);
if (appInfo.isInstantApp()) {
postEphemeralNotif(pkg, info.userId, appInfo, noMan);
}
}
int focusedId = ActivityManager.getService().getFocusedStackId();
if (focusedId == StackId.FULLSCREEN_WORKSPACE_STACK_ID
|| focusedId == StackId.FULLSCREEN_WORKSPACE_STACK_ID) {
checkStack(StackId.FULLSCREEN_WORKSPACE_STACK_ID, notifs, noMan, pm);
}
if (mDockedStackExists) {
checkStack(StackId.DOCKED_STACK_ID, notifs, noMan, pm);
}
} catch (RemoteException e) {
e.rethrowFromSystemServer();
@@ -521,8 +525,28 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks,
new UserHandle(v.second)));
}
private void checkStack(int stackId, ArraySet<Pair<String, Integer>> notifs,
NotificationManager noMan, IPackageManager pm) {
try {
StackInfo info = ActivityManager.getService().getStackInfo(stackId);
if (info == null || info.topActivity == null) return;
String pkg = info.topActivity.getPackageName();
if (!hasNotif(notifs, pkg, info.userId)) {
// TODO: Optimize by not always needing to get application info.
// Maybe cache non-ephemeral packages?
ApplicationInfo appInfo = pm.getApplicationInfo(pkg,
PackageManager.MATCH_UNINSTALLED_PACKAGES, info.userId);
if (appInfo.isInstantApp()) {
postEphemeralNotif(pkg, info.userId, appInfo, noMan, info.taskIds[info.taskIds.length - 1]);
}
}
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
}
private void postEphemeralNotif(String pkg, int userId, ApplicationInfo appInfo,
NotificationManager noMan) {
NotificationManager noMan, int taskId) {
final Bundle extras = new Bundle();
extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME,
mContext.getString(R.string.instant_apps));
@@ -531,12 +555,39 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks,
PendingIntent appInfoAction = PendingIntent.getActivity(mContext, 0,
new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
.setData(Uri.fromParts("package", pkg, null)), 0);
// TODO: Add action for go to web as well.
Action action = new Notification.Action.Builder(null, mContext.getString(R.string.app_info),
appInfoAction).build();
noMan.notifyAsUser(pkg, SystemMessage.NOTE_INSTANT_APPS,
new Notification.Builder(mContext, NotificationChannels.GENERAL)
Intent browserIntent = getTaskIntent(taskId, userId);
Notification.Builder builder = new Notification.Builder(mContext, NotificationChannels.GENERAL);
if (browserIntent != null) {
PendingIntent pendingIntent = PendingIntent.getActivity(mContext,
0 /* requestCode */, browserIntent, 0 /* flags */);
browserIntent.setComponent(null);
browserIntent.addFlags(Intent.FLAG_IGNORE_EPHEMERAL);
browserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
ComponentName aiaComponent = null;
try {
aiaComponent = AppGlobals.getPackageManager().getInstantAppInstallerComponent();
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
Intent goToWebIntent = new Intent()
.setComponent(aiaComponent)
.setAction(Intent.ACTION_VIEW)
.addCategory(Intent.CATEGORY_BROWSABLE)
.putExtra(Intent.EXTRA_PACKAGE_NAME, appInfo.packageName)
.putExtra(Intent.EXTRA_VERSION_CODE, appInfo.versionCode)
.putExtra(Intent.EXTRA_EPHEMERAL_FAILURE, pendingIntent);
PendingIntent webPendingIntent = PendingIntent.getActivity(mContext, 0, goToWebIntent, 0);
Action webAction = new Notification.Action.Builder(null, mContext.getString(R.string.go_to_web),
webPendingIntent).build();
builder.addAction(webAction);
}
noMan.notifyAsUser(pkg, SystemMessage.NOTE_INSTANT_APPS, builder
.addExtras(extras)
.addAction(action)
.setContentIntent(appInfoAction)
@@ -551,6 +602,17 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks,
new UserHandle(userId));
}
private Intent getTaskIntent(int taskId, int userId) {
List<ActivityManager.RecentTaskInfo> tasks = mContext.getSystemService(ActivityManager.class)
.getRecentTasksForUser(NUM_TASKS_FOR_INSTANT_APP_INFO, 0, userId);
for (int i = 0; i < tasks.size(); i++) {
if (tasks.get(i).id == taskId) {
return tasks.get(i).baseIntent;
}
}
return null;
}
private boolean hasNotif(ArraySet<Pair<String, Integer>> notifs, String pkg, int userId) {
Pair<String, Integer> key = new Pair<>(pkg, userId);
if (notifs.remove(key)) {