Home | History | Annotate | Download | only in launcher3
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.launcher3;
     18 
     19 import android.content.BroadcastReceiver;
     20 import android.content.Context;
     21 import android.content.Intent;
     22 import android.content.IntentFilter;
     23 import android.os.Bundle;
     24 import android.util.Log;
     25 import android.view.View;
     26 import android.view.ViewParent;
     27 
     28 public class Stats {
     29 
     30     /**
     31      * Implemented by containers to provide a launch source for a given child.
     32      */
     33     public interface LaunchSourceProvider {
     34         void fillInLaunchSourceData(View v, Bundle sourceData);
     35     }
     36 
     37     /**
     38      * Helpers to add the source to a launch intent.
     39      */
     40     public static class LaunchSourceUtils {
     41         /**
     42          * Create a default bundle for LaunchSourceProviders to fill in their data.
     43          */
     44         public static Bundle createSourceData() {
     45             Bundle sourceData = new Bundle();
     46             sourceData.putString(SOURCE_EXTRA_CONTAINER, CONTAINER_HOMESCREEN);
     47             // Have default container/sub container pages
     48             sourceData.putInt(SOURCE_EXTRA_CONTAINER_PAGE, 0);
     49             sourceData.putInt(SOURCE_EXTRA_SUB_CONTAINER_PAGE, 0);
     50             return sourceData;
     51         }
     52 
     53         /**
     54          * Finds the next launch source provider in the parents of the view hierarchy and populates
     55          * the source data from that provider.
     56          */
     57         public static void populateSourceDataFromAncestorProvider(View v, Bundle sourceData) {
     58             if (v == null) {
     59                 return;
     60             }
     61 
     62             Stats.LaunchSourceProvider provider = null;
     63             ViewParent parent = v.getParent();
     64             while (parent != null && parent instanceof View) {
     65                 if (parent instanceof Stats.LaunchSourceProvider) {
     66                     provider = (Stats.LaunchSourceProvider) parent;
     67                     break;
     68                 }
     69                 parent = parent.getParent();
     70             }
     71 
     72             if (provider != null) {
     73                 provider.fillInLaunchSourceData(v, sourceData);
     74             } else if (LauncherAppState.isDogfoodBuild()) {
     75                 throw new RuntimeException("Expected LaunchSourceProvider");
     76             }
     77         }
     78     }
     79 
     80     private static final boolean DEBUG_BROADCASTS = false;
     81 
     82     public static final String ACTION_LAUNCH = "com.android.launcher3.action.LAUNCH";
     83     public static final String EXTRA_INTENT = "intent";
     84     public static final String EXTRA_CONTAINER = "container";
     85     public static final String EXTRA_SCREEN = "screen";
     86     public static final String EXTRA_CELLX = "cellX";
     87     public static final String EXTRA_CELLY = "cellY";
     88     public static final String EXTRA_SOURCE = "source";
     89 
     90     public static final String SOURCE_EXTRA_CONTAINER = "container";
     91     public static final String SOURCE_EXTRA_CONTAINER_PAGE = "container_page";
     92     public static final String SOURCE_EXTRA_SUB_CONTAINER = "sub_container";
     93     public static final String SOURCE_EXTRA_SUB_CONTAINER_PAGE = "sub_container_page";
     94 
     95     public static final String CONTAINER_SEARCH_BOX = "search_box";
     96     public static final String CONTAINER_ALL_APPS = "all_apps";
     97     public static final String CONTAINER_HOMESCREEN = "homescreen"; // aka. Workspace
     98     public static final String CONTAINER_HOTSEAT = "hotseat";
     99 
    100     public static final String SUB_CONTAINER_FOLDER = "folder";
    101     public static final String SUB_CONTAINER_ALL_APPS_A_Z = "a-z";
    102     public static final String SUB_CONTAINER_ALL_APPS_PREDICTION = "prediction";
    103     public static final String SUB_CONTAINER_ALL_APPS_SEARCH = "search";
    104 
    105     private final Launcher mLauncher;
    106     private final String mLaunchBroadcastPermission;
    107 
    108     public Stats(Launcher launcher) {
    109         mLauncher = launcher;
    110         mLaunchBroadcastPermission =
    111                 launcher.getResources().getString(R.string.receive_launch_broadcasts_permission);
    112 
    113         if (DEBUG_BROADCASTS) {
    114             launcher.registerReceiver(
    115                     new BroadcastReceiver() {
    116                         @Override
    117                         public void onReceive(Context context, Intent intent) {
    118                             Log.v("Stats", "got broadcast: " + intent + " for launched intent: "
    119                                     + intent.getStringExtra(EXTRA_INTENT));
    120                         }
    121                     },
    122                     new IntentFilter(ACTION_LAUNCH),
    123                     mLaunchBroadcastPermission,
    124                     null
    125             );
    126         }
    127     }
    128 
    129     public void recordLaunch(View v, Intent intent, ShortcutInfo shortcut) {
    130         intent = new Intent(intent);
    131         intent.setSourceBounds(null);
    132 
    133         final String flat = intent.toUri(0);
    134         Intent broadcastIntent = new Intent(ACTION_LAUNCH).putExtra(EXTRA_INTENT, flat);
    135 
    136         if (shortcut != null) {
    137             broadcastIntent.putExtra(EXTRA_CONTAINER, shortcut.container)
    138                     .putExtra(EXTRA_SCREEN, shortcut.screenId)
    139                     .putExtra(EXTRA_CELLX, shortcut.cellX)
    140                     .putExtra(EXTRA_CELLY, shortcut.cellY);
    141         }
    142 
    143         Bundle sourceExtras = LaunchSourceUtils.createSourceData();
    144         LaunchSourceUtils.populateSourceDataFromAncestorProvider(v, sourceExtras);
    145         broadcastIntent.putExtra(EXTRA_SOURCE, sourceExtras);
    146 
    147         String[] packages = mLauncher.getResources().getStringArray(R.array.launch_broadcast_targets);
    148         for(String p: packages) {
    149             broadcastIntent.setPackage(p);
    150             mLauncher.sendBroadcast(broadcastIntent, mLaunchBroadcastPermission);
    151         }
    152     }
    153 }
    154